blob: a3157a38cad8f95d3258baea333039632a1dba8e [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{
developerea4bcce2022-09-13 15:26:13 +08003624 char config_file[MAX_BUF_SIZE] = {'\0'};
3625 char buf[MAX_BUF_SIZE] = {'\0'};
3626 struct params list;
3627
3628 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3629 if (threshold < 256 || threshold > 2346 )
3630 return RETURN_ERR;
3631 list.name = "fragm_threshold";
3632 snprintf(buf, sizeof(buf), "%d", threshold);
3633 list.value = buf;
3634
3635 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
3636 wifi_hostapdWrite(config_file, &list, 1);
3637 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08003638
developerea4bcce2022-09-13 15:26:13 +08003639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003640
3641 return RETURN_OK;
3642}
3643
3644// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
3645INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
3646{
3647 //Save config and Apply instantly
3648 return RETURN_ERR;
3649}
3650
3651// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
3652INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
3653{
3654 return RETURN_ERR;
3655}
3656
3657// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
3658INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
3659{
3660 //Apply instantly
3661 return RETURN_ERR;
3662}
3663
3664//P2 // outputs the number of Tx streams
3665INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
3666{
3667 return RETURN_ERR;
3668}
3669
3670//P2 // sets the number of Tx streams to an enviornment variable
3671INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
3672{
3673 //save to wifi config, wait for wifi reset or wifi_pushTxChainMask to apply
3674 return RETURN_ERR;
3675}
3676
3677//P2 // outputs the number of Rx streams
3678INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
3679{
3680 if (NULL == output_int)
3681 return RETURN_ERR;
3682 *output_int = 1;
3683 return RETURN_OK;
3684}
3685
3686//P2 // sets the number of Rx streams to an enviornment variable
3687INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
3688{
3689 //save to wifi config, wait for wifi reset or wifi_pushRxChainMask to apply
3690 return RETURN_ERR;
3691}
3692
3693//Get radio RDG enable setting
3694INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
3695{
3696 if (NULL == output_bool)
3697 return RETURN_ERR;
3698 *output_bool = TRUE;
3699 return RETURN_OK;
3700}
3701
3702//Get radio RDG enable setting
3703INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
3704{
3705 if (NULL == output_bool)
3706 return RETURN_ERR;
3707 *output_bool = TRUE;
3708 return RETURN_OK;
3709}
3710
3711//Set radio RDG enable setting
3712INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
3713{
3714 return RETURN_ERR;
3715}
3716
3717//Get radio ADDBA enable setting
3718INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
3719{
3720 if (NULL == output_bool)
3721 return RETURN_ERR;
3722 *output_bool = TRUE;
3723 return RETURN_OK;
3724}
3725
3726//Set radio ADDBA enable setting
3727INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
3728{
3729 return RETURN_ERR;
3730}
3731
3732//Get radio auto block ack enable setting
3733INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
3734{
3735 if (NULL == output_bool)
3736 return RETURN_ERR;
3737 *output_bool = TRUE;
3738 return RETURN_OK;
3739}
3740
3741//Set radio auto block ack enable setting
3742INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
3743{
3744 return RETURN_ERR;
3745}
3746
3747//Get radio 11n pure mode enable support
3748INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
3749{
3750 if (NULL == output_bool)
3751 return RETURN_ERR;
3752 *output_bool = TRUE;
3753 return RETURN_OK;
3754}
3755
3756//Get radio 11n pure mode enable setting
3757INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
3758{
3759 if (NULL == output_bool)
3760 return RETURN_ERR;
3761 *output_bool = TRUE;
3762 return RETURN_OK;
3763}
3764
3765//Set radio 11n pure mode enable setting
3766INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
3767{
3768 return RETURN_ERR;
3769}
3770
3771//Get radio IGMP snooping enable setting
3772INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
3773{
3774 if (NULL == output_bool)
3775 return RETURN_ERR;
3776 *output_bool = TRUE;
3777 return RETURN_OK;
3778}
3779
3780//Set radio IGMP snooping enable setting
3781INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
3782{
3783 return RETURN_ERR;
3784}
3785
3786//Get the Reset count of radio
3787INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
3788{
3789 if (NULL == output_int)
3790 return RETURN_ERR;
3791 *output_int = (radioIndex==0)? 1: 3;
3792
3793 return RETURN_OK;
3794}
3795
3796
3797//---------------------------------------------------------------------------------------------------
3798//
3799// Additional Wifi AP level APIs used for Access Point devices
3800//
3801//---------------------------------------------------------------------------------------------------
3802
3803// creates a new ap and pushes these parameters to the hardware
3804INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
3805{
3806 char buf[1024];
3807 char cmd[128];
3808
3809 if (NULL == essid)
3810 return RETURN_ERR;
3811
3812 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
3813 _syscmd(cmd, buf, sizeof(buf));
3814
3815 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
3816 _syscmd(cmd, buf, sizeof(buf));
3817
3818 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
3819
3820 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
3821 _syscmd(cmd, buf, sizeof(buf));
3822
3823 return RETURN_OK;
3824}
3825
3826// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
3827INT wifi_deleteAp(INT apIndex)
3828{
3829 char buf[1024];
3830 char cmd[128];
3831
3832 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
3833 _syscmd(cmd, buf, sizeof(buf));
3834
3835 wifi_removeApSecVaribles(apIndex);
3836
3837 return RETURN_OK;
3838}
3839
3840// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
3841INT wifi_getApName(INT apIndex, CHAR *output_string)
3842{
3843 if(NULL == output_string)
3844 return RETURN_ERR;
3845
3846 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
3847 return RETURN_OK;
3848}
3849
3850// Outputs the index number in that corresponds to the SSID string
3851INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
3852{
3853 CHAR *pos = NULL;
3854
3855 *output_int = -1;
3856 pos = strstr(inputSsidString, AP_PREFIX);
3857 if(pos)
3858 {
3859 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
3860 return RETURN_OK;
3861 }
3862 return RETURN_ERR;
3863}
3864
3865INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
3866{
3867 return wifi_getIndexFromName(inputSsidString, output_int);
3868}
3869
3870// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
3871INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
3872{
3873 char buf[MAX_BUF_SIZE] = {0};
3874 char cmd[MAX_CMD_SIZE] = {0};
3875 char config_file[MAX_BUF_SIZE] = {0};
3876
3877 if(NULL == output_string)
3878 return RETURN_ERR;
3879
3880 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3881 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
3882 if((strcmp(buf,"3")==0))
3883 snprintf(output_string, 32, "WPAand11i");
3884 else if((strcmp(buf,"2")==0))
3885 snprintf(output_string, 32, "11i");
3886 else if((strcmp(buf,"1")==0))
3887 snprintf(output_string, 32, "WPA");
3888 else
3889 snprintf(output_string, 32, "None");
3890
3891 return RETURN_OK;
3892}
3893
3894// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
3895INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
3896{
3897 char config_file[MAX_BUF_SIZE] = {0};
3898 struct params list;
3899
3900 if (NULL == beaconTypeString)
3901 return RETURN_ERR;
3902 list.name = "wpa";
3903 list.value = "0";
3904
3905 if((strcmp(beaconTypeString,"WPAand11i")==0))
3906 list.value="3";
3907 else if((strcmp(beaconTypeString,"11i")==0))
3908 list.value="2";
3909 else if((strcmp(beaconTypeString,"WPA")==0))
3910 list.value="1";
3911
3912 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3913 wifi_hostapdWrite(config_file, &list, 1);
3914 wifi_hostapdProcessUpdate(apIndex, &list, 1);
3915 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
3916 return RETURN_OK;
3917}
3918
3919// sets the beacon interval on the hardware for this AP
3920INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
3921{
developer5f222492022-09-13 15:21:52 +08003922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3923 struct params params={'\0'};
3924 char buf[MAX_BUF_SIZE] = {'\0'};
3925 char config_file[MAX_BUF_SIZE] = {'\0'};
3926
3927 params.name = "beacon_int";
3928 snprintf(buf, sizeof(buf), "%u", beaconInterval);
3929 params.value = buf;
3930
3931 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
3932 wifi_hostapdWrite(config_file, &params, 1);
3933
3934 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3936 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003937}
3938
3939INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
3940{
3941 //save config and apply instantly
3942 return RETURN_ERR;
3943}
3944
3945// Get the packet size threshold supported.
3946INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
3947{
3948 //save config and apply instantly
3949 if (NULL == output_bool)
3950 return RETURN_ERR;
3951 *output_bool = FALSE;
3952 return RETURN_OK;
3953}
3954
3955// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
3956INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
3957{
3958 char cmd[128];
3959 char buf[512];
3960
3961 if (threshold > 0)
3962 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
3963 else
3964 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
3965 _syscmd(cmd, buf, sizeof(buf));
3966
3967 return RETURN_OK;
3968}
3969
3970// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
3971INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
3972{
3973 if (NULL == output_string)
3974 return RETURN_ERR;
3975 snprintf(output_string, 32, "TKIPandAESEncryption");
3976 return RETURN_OK;
3977
3978}
3979
3980// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
3981INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
3982{
3983 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3984 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
3985
3986 if(NULL == output_string)
3987 return RETURN_ERR;
3988
3989 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3990 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
3991
3992 if(strcmp(buf,"0")==0)
3993 {
3994 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
3995 snprintf(output_string, 32, "None");
3996 return RETURN_OK;
3997 }
3998 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
3999 param_name = "rsn_pairwise";
4000 else if((strcmp(buf,"1")==0))
4001 param_name = "wpa_pairwise";
4002 else
4003 return RETURN_ERR;
4004 memset(output_string,'\0',32);
4005 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4006 wifi_hostapdRead(config_file,param_name,output_string,32);
4007 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4008
4009 if(strcmp(output_string,"TKIP") == 0)
4010 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4011 else if(strcmp(output_string,"CCMP") == 0)
4012 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4013 else if(strcmp(output_string,"TKIP CCMP") == 0)
4014 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4015
4016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4017 return RETURN_OK;
4018}
4019
4020// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4021INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4022{
4023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4024 struct params params={'\0'};
4025 char output_string[32];
4026 char config_file[MAX_BUF_SIZE] = {0};
4027
4028 memset(output_string,'\0',32);
4029 wifi_getApWpaEncryptionMode(apIndex,output_string);
4030
4031 if(strcmp(encMode, "TKIPEncryption") == 0)
4032 params.value = "TKIP";
4033 else if(strcmp(encMode,"AESEncryption") == 0)
4034 params.value = "CCMP";
4035 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4036 params.value = "TKIP CCMP";
4037
4038 if((strcmp(output_string,"WPAand11i")==0))
4039 {
4040 params.name = "wpa_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 params.name,"rsn_pairwise";
4046 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4047 wifi_hostapdWrite(config_file, &params, 1);
4048 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4049
4050 return RETURN_OK;
4051 }
4052 else if((strcmp(output_string,"11i")==0))
4053 {
4054 params.name = "rsn_pairwise";
4055 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4056 wifi_hostapdWrite(config_file, &params, 1);
4057 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4058 return RETURN_OK;
4059 }
4060 else if((strcmp(output_string,"WPA")==0))
4061 {
4062 params.name = "wpa_pairwise";
4063 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4064 wifi_hostapdWrite(config_file, &params, 1);
4065 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4066 return RETURN_OK;
4067 }
4068
4069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4070 return RETURN_OK;
4071}
4072
4073// deletes internal security varable settings for this ap
4074INT wifi_removeApSecVaribles(INT apIndex)
4075{
4076 //TODO: remove the entry in hostapd config file
4077 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4078 //_syscmd(cmd, buf, sizeof(buf));
4079
4080 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4081 //_syscmd(cmd, buf, sizeof(buf));
4082 return RETURN_ERR;
4083}
4084
4085// changes the hardware settings to disable encryption on this ap
4086INT wifi_disableApEncryption(INT apIndex)
4087{
4088 //Apply instantly
4089 return RETURN_ERR;
4090}
4091
4092// set the authorization mode on this ap
4093// mode mapping as: 1: open, 2: shared, 4:auto
4094INT wifi_setApAuthMode(INT apIndex, INT mode)
4095{
4096 //Apply instantly
4097 return RETURN_ERR;
4098}
4099
4100// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4101INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4102{
4103 //save to wifi config, and wait for wifi restart to apply
4104 struct params params={'\0'};
4105 char config_file[MAX_BUF_SIZE] = {0};
4106 int ret;
4107
4108 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4109 if(authMode == NULL)
4110 return RETURN_ERR;
4111
4112 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4113 params.name = "wpa_key_mgmt";
4114
4115 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4116 params.value = "WPA-PSK";
4117 else if(strcmp(authMode,"EAPAuthentication") == 0)
4118 params.value = "WPA-EAP";
4119 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4120 return RETURN_OK; //This is taken careof in beaconType
4121
4122 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4123 ret=wifi_hostapdWrite(config_file,&params,1);
4124 if(!ret)
4125 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4127
4128 return ret;
4129}
4130
4131// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4132INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4133{
4134 //save to wifi config, and wait for wifi restart to apply
4135 char BeaconType[50] = {0};
4136 char config_file[MAX_BUF_SIZE] = {0};
4137
4138 *authMode = 0;
4139 wifi_getApBeaconType(apIndex,BeaconType);
4140 printf("%s____%s \n",__FUNCTION__,BeaconType);
4141
4142 if(strcmp(BeaconType,"None") == 0)
4143 strcpy(authMode,"None");
4144 else
4145 {
4146 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4147 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4148 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4149 if(strcmp(authMode,"WPA-PSK") == 0)
4150 strcpy(authMode,"SharedAuthentication");
4151 else if(strcmp(authMode,"WPA-EAP") == 0)
4152 strcpy(authMode,"EAPAuthentication");
4153 }
4154
4155 return RETURN_OK;
4156}
4157
4158// Outputs the number of stations associated per AP
4159INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4160{
4161 char cmd[128]={0};
4162 char buf[128]={0};
4163 BOOL status = false;
4164
4165 if(apIndex > MAX_APS)
4166 return RETURN_ERR;
4167
4168 wifi_getApEnable(apIndex,&status);
4169 if (!status)
4170 return RETURN_OK;
4171
4172 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4173 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4174 _syscmd(cmd, buf, sizeof(buf));
4175 sscanf(buf,"%lu", output_ulong);
4176
4177 return RETURN_OK;
4178}
4179
4180// manually removes any active wi-fi association with the device specified on this ap
4181INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4182{
4183 char buf[126]={'\0'};
4184
4185 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4186 system(buf);
4187
4188 return RETURN_OK;
4189}
4190
4191// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4192INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4193{
4194 if(NULL == output_int)
4195 return RETURN_ERR;
4196 *output_int = apIndex%2;
4197 return RETURN_OK;
4198}
4199
4200// sets the radio index for the specific ap
4201INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4202{
4203 //set to config only and wait for wifi reset to apply settings
4204 return RETURN_ERR;
4205}
4206
4207// Get the ACL MAC list per AP
4208INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4209{
4210 char cmd[MAX_CMD_SIZE]={'\0'};
4211 int ret = 0;
4212
4213 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4214 ret = _syscmd(cmd,macArray,buf_size);
4215 if (ret != 0)
4216 return RETURN_ERR;
4217
4218 return RETURN_OK;
4219}
4220
developere6aafda2022-09-13 14:59:28 +08004221INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4222{
4223 char cmd[MAX_CMD_SIZE]={'\0'};
4224 int ret = 0;
4225
4226 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4227 ret = _syscmd(cmd,macArray,buf_size);
4228 if (ret != 0)
4229 return RETURN_ERR;
4230
4231 return RETURN_OK;
4232}
4233
4234
developer06a01d92022-09-07 16:32:39 +08004235// Get the list of stations associated per AP
4236INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4237{
4238 char cmd[128];
4239
4240 if(apIndex > 3) //Currently supporting apIndex upto 3
4241 return RETURN_ERR;
4242 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
4243 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
4244 _syscmd(cmd, macArray, buf_size);
4245
4246 return RETURN_OK;
4247}
4248
4249// adds the mac address to the filter list
4250//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4251INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4252{
4253 char cmd[MAX_CMD_SIZE]={'\0'};
4254 char buf[MAX_BUF_SIZE]={'\0'};
4255
4256#if 0
4257 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4258 if(_syscmd(cmd,buf,sizeof(buf)))
4259 return RETURN_ERR;
4260#endif
4261 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
4262 if(_syscmd(cmd,buf,sizeof(buf)))
4263 return RETURN_ERR;
4264
4265 return RETURN_OK;
4266}
4267
4268// deletes the mac address from the filter list
4269//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4270INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4271{
4272 char cmd[MAX_CMD_SIZE]={'\0'};
4273 char buf[MAX_BUF_SIZE]={'\0'};
4274
4275#if 0
4276 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4277 if(_syscmd(cmd,buf,sizeof(buf)))
4278 return RETURN_ERR;
4279
4280#endif
4281 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
4282 if(_syscmd(cmd,buf,sizeof(buf)))
4283 return RETURN_ERR;
4284
4285 return RETURN_OK;
4286}
4287
4288// outputs the number of devices in the filter list
4289INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
4290{
developere6aafda2022-09-13 14:59:28 +08004291 char cmd[MAX_BUF_SIZE]={0};
4292 char buf[MAX_CMD_SIZE]={0};
4293
4294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4295 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08004296 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08004297
4298 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
4299 _syscmd(cmd, buf, sizeof(buf));
4300
4301 *output_uint = atoi(buf);
4302
4303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4304 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004305}
4306
4307INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
4308{
4309 char cmd[128]={'\0'};
4310 char buf[128]={'\0'};
4311
4312 if(strcmp(action,"DENY")==0)
4313 {
4314 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
4315 system(buf);
4316 return RETURN_OK;
4317 }
4318
4319 if(strcmp(action,"ALLOW")==0)
4320 {
4321 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
4322 system(buf);
4323 return RETURN_OK;
4324 }
4325
4326 return RETURN_ERR;
4327
4328}
4329
4330// enable kick for devices on acl black list
4331INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
4332{
4333 char aclArray[512] = {0}, *acl = NULL;
4334 char assocArray[512] = {0}, *asso = NULL;
4335
developere6aafda2022-09-13 14:59:28 +08004336 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08004337 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
4338
4339 // if there are no devices connected there is nothing to do
4340 if (strlen(assocArray) < 17)
4341 return RETURN_OK;
4342
4343 if (enable == TRUE)
4344 {
4345 //kick off the MAC which is in ACL array (deny list)
4346 acl = strtok(aclArray, "\r\n");
4347 while (acl != NULL) {
4348 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
4349 wifi_kickApAssociatedDevice(apIndex, acl);
4350
4351 acl = strtok(NULL, "\r\n");
4352 }
developere6aafda2022-09-13 14:59:28 +08004353 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08004354 }
4355 else
4356 {
developere6aafda2022-09-13 14:59:28 +08004357 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08004358 }
4359
4360#if 0
4361 //TODO: need to revisit below implementation
4362 char aclArray[512]={0}, *acl=NULL;
4363 char assocArray[512]={0}, *asso=NULL;
4364 char buf[256]={'\0'};
4365 char action[10]={'\0'};
4366 FILE *fr=NULL;
4367 char interface[10]={'\0'};
4368 char config_file[MAX_BUF_SIZE] = {0};
4369
4370 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
4371 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
4372 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4373 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
4374
4375 sprintf(buf,"iptables -F WifiServices%d",apIndex);
4376 system(buf);
4377 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
4378 system(buf);
4379 sprintf(buf,"iptables -X WifiServices%d",apIndex);
4380 system(buf);
4381 sprintf(buf,"iptables -N WifiServices%d",apIndex);
4382 system(buf);
4383 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
4384 system(buf);
4385
4386 if ( enable == TRUE )
4387 {
4388 int device_count=0;
4389 strcpy(action,"DENY");
4390 //kick off the MAC which is in ACL array (deny list)
4391 acl = strtok (aclArray,",");
4392 while (acl != NULL) {
4393 if(strlen(acl)>=17)
4394 {
4395 apply_rules(apIndex, acl,action,interface);
4396 device_count++;
4397 //Register mac to be blocked ,in syscfg.db persistent storage
4398 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
4399 system(buf);
4400 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
4401 system(buf);
4402 system("syscfg commit");
4403
4404 wifi_kickApAssociatedDevice(apIndex, acl);
4405 }
4406 acl = strtok (NULL, ",");
4407 }
4408 }
4409 else
4410 {
4411 int device_count=0;
4412 char cmdmac[20]={'\0'};
4413 strcpy(action,"ALLOW");
4414 //kick off the MAC which is not in ACL array (allow list)
4415 acl = strtok (aclArray,",");
4416 while (acl != NULL) {
4417 if(strlen(acl)>=17)
4418 {
4419 apply_rules(apIndex, acl,action,interface);
4420 device_count++;
4421 //Register mac to be Allowed ,in syscfg.db persistent storage
4422 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
4423 system(buf);
4424 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
4425 system(buf);
4426 sprintf(cmdmac,"%s",acl);
4427 }
4428 acl = strtok (NULL, ",");
4429 }
4430 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
4431 system(buf);
4432
4433 //Disconnect the mac which is not in ACL
4434 asso = strtok (assocArray,",");
4435 while (asso != NULL) {
4436 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
4437 wifi_kickApAssociatedDevice(apIndex, asso);
4438 asso = strtok (NULL, ",");
4439 }
4440 }
4441#endif
4442 return RETURN_OK;
4443}
4444
4445INT wifi_setPreferPrivateConnection(BOOL enable)
4446{
4447 char interface_name[100] = {0},ssid_cur_value[50] = {0};
4448 char buf[1024] = {0};
4449
4450 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
4451 if(enable == TRUE)
4452 {
4453 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4454 sprintf(buf,"ifconfig %s down" ,interface_name);
4455 system(buf);
4456 memset(buf,0,sizeof(buf));
4457 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4458 sprintf(buf,"ifconfig %s down" ,interface_name);
4459 system(buf);
4460 }
4461 else
4462 {
4463 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
4464 if(strcmp(ssid_cur_value,"1") == 0)
4465 wifi_RestartPrivateWifi_5G();
4466 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
4467 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
4468 if(strcmp(ssid_cur_value,"1") == 0)
4469 wifi_RestartHostapd_2G();
4470 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
4471 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
4472 if(strcmp(ssid_cur_value,"1") == 0)
4473 wifi_RestartHostapd_5G();
4474 }
4475 return RETURN_OK;
4476}
4477
4478// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
4479INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
4480{
4481 int items = 1;
4482 struct params list[2];
4483 char buf[MAX_BUF_SIZE] = {0};
4484 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08004485 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08004486
4487 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08004488
developer10adcc12022-09-13 14:39:17 +08004489 if (filterMode == 0) {
4490 sprintf(buf, "%d", 0);
4491 list[0].value = buf;
4492
4493 char cmd[128], rtn[128];
4494 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
4495 _syscmd(cmd, rtn, sizeof(rtn));
4496 memset(cmd,0,sizeof(cmd));
4497 // Delete deny_mac_file in hostapd configuration
4498 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
4499 _syscmd(cmd, rtn, sizeof(rtn));
4500 }
4501 else if (filterMode == 1) {
4502 sprintf(buf, "%d", filterMode);
4503 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08004504 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
4505 list[1].name = "accept_mac_file";
4506 list[1].value = acl_file;
4507 items = 2;
developer10adcc12022-09-13 14:39:17 +08004508 } else if (filterMode == 2) {
4509 //TODO: deny_mac_file
4510 sprintf(buf, "%d", 0);
4511 list[0].value = buf;
4512 list[1].name = "deny_mac_file";
4513 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
4514 list[1].value = deny_file;
4515 items = 2;
4516 } else {
4517 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004518 }
developer10adcc12022-09-13 14:39:17 +08004519
developer06a01d92022-09-07 16:32:39 +08004520 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4521 wifi_hostapdWrite(config_file, list, items);
4522
4523 return RETURN_OK;
4524
4525#if 0
4526 if(apIndex==0 || apIndex==1)
4527 {
4528 //set the filtermode
4529 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
4530 system(buf);
4531 system("syscfg commit");
4532
4533 if(filterMode==0)
4534 {
4535 sprintf(buf,"iptables -F WifiServices%d",apIndex);
4536 system(buf);
4537 return RETURN_OK;
4538 }
4539 }
4540 return RETURN_OK;
4541#endif
4542}
4543
4544// 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.
4545INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
4546{
4547 return RETURN_ERR;
4548}
4549
4550// gets the vlan ID for this ap from an internal enviornment variable
4551INT wifi_getApVlanID(INT apIndex, INT *output_int)
4552{
4553 if(apIndex=0)
4554 {
4555 *output_int=100;
4556 return RETURN_OK;
4557 }
4558
4559 return RETURN_ERR;
4560}
4561
4562// sets the vlan ID for this ap to an internal enviornment variable
4563INT wifi_setApVlanID(INT apIndex, INT vlanId)
4564{
4565 //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)
4566 return RETURN_ERR;
4567}
4568
4569// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
4570INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
4571{
4572 snprintf(bridgeName, 32, "brlan0");
4573 snprintf(IP, 32, "10.0.0.1");
4574 snprintf(subnet, 32, "255.255.255.0");
4575
4576 return RETURN_OK;
4577}
4578
4579//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
4580INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
4581{
4582 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
4583 return RETURN_ERR;
4584}
4585
4586// reset the vlan configuration for this ap
4587INT wifi_resetApVlanCfg(INT apIndex)
4588{
4589 //TODO: remove existing vlan for this ap
4590
4591 //Reapply vlan settings
4592 wifi_pushBridgeInfo(apIndex);
4593
4594 return RETURN_ERR;
4595}
4596
4597// 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.
4598INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
4599{
4600 return RETURN_ERR;
4601}
4602
4603// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
4604INT wifi_startHostApd()
4605{
4606 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4607 system("systemctl start hostapd.service");
4608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4609 return RETURN_OK;
4610 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
4611}
4612
4613// stops hostapd
4614INT wifi_stopHostApd()
4615{
4616 char cmd[128] = {0};
4617 char buf[128] = {0};
4618
4619 sprintf(cmd,"systemctl stop hostapd");
4620 _syscmd(cmd, buf, sizeof(buf));
4621
4622 return RETURN_OK;
4623}
4624
4625// restart hostapd dummy function
4626INT wifi_restartHostApd()
4627{
4628 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4629 system("systemctl restart hostapd-global");
4630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4631
4632 return RETURN_OK;
4633}
4634
4635static int align_hostapd_config(int index)
4636{
4637 ULONG lval;
4638 wifi_getRadioChannel(index%2, &lval);
4639 wifi_setRadioChannel(index%2, lval);
4640}
4641
4642// sets the AP enable status variable for the specified ap.
4643INT wifi_setApEnable(INT apIndex, BOOL enable)
4644{
4645 char config_file[MAX_BUF_SIZE] = {0};
4646 char cmd[MAX_CMD_SIZE] = {0};
4647 char buf[MAX_BUF_SIZE] = {0};
4648 BOOL status;
4649
4650 wifi_getApEnable(apIndex,&status);
4651 if (enable == status)
4652 return RETURN_OK;
4653
4654 if (enable == TRUE) {
4655 int radioIndex = apIndex % NUMBER_OF_RADIOS;
4656 align_hostapd_config(apIndex);
4657 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4658 //Hostapd will bring up this interface
4659 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
4660 _syscmd(cmd, buf, sizeof(buf));
4661 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
4662 _syscmd(cmd, buf, sizeof(buf));
4663 }
4664 else {
4665 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
4666 _syscmd(cmd, buf, sizeof(buf));
4667 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
4668 _syscmd(cmd, buf, sizeof(buf));
4669 }
4670 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
4671 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
4672 _syscmd(cmd, buf, sizeof(buf));
4673 //Wait for wifi up/down to apply
4674 return RETURN_OK;
4675}
4676
4677// Outputs the setting of the internal variable that is set by wifi_setApEnable().
4678INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
4679{
4680 char cmd[MAX_CMD_SIZE] = {'\0'};
4681 char buf[MAX_BUF_SIZE] = {'\0'};
4682
4683 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
4684 return RETURN_ERR;
4685
4686 *output_bool = 0;
4687
4688 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
4689 {
4690 sprintf(cmd, "%s%s%d%s", "ifconfig ", AP_PREFIX, apIndex, " | grep UP");
4691 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
4692 }
4693
4694 return RETURN_OK;
4695}
4696
4697// Outputs the AP "Enabled" "Disabled" status from driver
4698INT wifi_getApStatus(INT apIndex, CHAR *output_string)
4699{
4700 char cmd[128] = {0};
4701 char buf[128] = {0};
4702 BOOL output_bool;
4703
4704 if ( NULL == output_string)
4705 return RETURN_ERR;
4706 wifi_getApEnable(apIndex,&output_bool);
4707
4708 if(output_bool == 1)
4709 snprintf(output_string, 32, "Up");
4710 else
4711 snprintf(output_string, 32, "Disable");
4712
4713 return RETURN_OK;
4714}
4715
4716//Indicates whether or not beacons include the SSID name.
4717// outputs a 1 if SSID on the AP is enabled, else outputs 0
4718INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
4719{
4720 //get the running status
4721 char config_file[MAX_BUF_SIZE] = {0};
4722 char buf[16] = {0};
4723
4724 if (!output)
4725 return RETURN_ERR;
4726
4727 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4728 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
4729 *output = (strncmp("0",buf,1) == 0);
4730
4731 return RETURN_OK;
4732}
4733
4734// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
4735INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
4736{
4737 //store the config, apply instantly
4738 char config_file[MAX_BUF_SIZE] = {0};
4739 struct params list;
4740
4741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4742 list.name = "ignore_broadcast_ssid";
4743 list.value = enable?"0":"1";
4744
4745 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4746 wifi_hostapdWrite(config_file, &list, 1);
4747 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4748 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08004749 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08004750 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4751
4752 return RETURN_OK;
4753}
4754
4755//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
4756INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
4757{
4758 //get the running status
4759 if(!output_uint)
4760 return RETURN_ERR;
4761 *output_uint=16;
4762 return RETURN_OK;
4763}
4764
4765INT wifi_setApRetryLimit(INT apIndex, UINT number)
4766{
4767 //apply instantly
4768 return RETURN_ERR;
4769}
4770
4771//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
4772INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
4773{
4774 if(!output)
4775 return RETURN_ERR;
4776 *output=TRUE;
4777 return RETURN_OK;
4778}
4779
4780//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
4781INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
4782{
4783 //get the running status from driver
4784 if(!output)
4785 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08004786
4787 char config_file[MAX_BUF_SIZE] = {0};
4788 char buf[16] = {0};
4789
4790 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4791 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
4792 if (strncmp("1",buf,1) == 0)
4793 *output = TRUE;
4794 else
4795 *output = FALSE;
4796
developer06a01d92022-09-07 16:32:39 +08004797 return RETURN_OK;
4798}
4799
4800//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
4801INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
4802{
4803 //get the running status from driver
4804 if(!output)
4805 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08004806
4807 char config_file[MAX_BUF_SIZE] = {0};
4808 char buf[16] = {0};
4809
4810 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4811 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
4812 if (strncmp("1",buf,1) == 0)
4813 *output = TRUE;
4814 else
4815 *output = FALSE;
4816
developer06a01d92022-09-07 16:32:39 +08004817 return RETURN_OK;
4818}
4819
4820// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
4821INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
4822{
4823 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08004824 char config_file[MAX_BUF_SIZE] = {0};
4825 struct params list;
4826
4827 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4828 list.name = "wmm_enabled";
4829 list.value = enable?"1":"0";
4830
4831 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4832 wifi_hostapdWrite(config_file, &list, 1);
4833 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4834 wifi_reloadAp(apIndex);
4835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4836
4837 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004838}
4839
4840//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.
4841INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
4842{
4843 //get the running status from driver
4844 if(!output)
4845 return RETURN_ERR;
4846 *output=TRUE;
4847 return RETURN_OK;
4848}
4849
4850// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
4851INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
4852{
4853 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08004854 char config_file[MAX_BUF_SIZE] = {0};
4855 struct params list;
4856
4857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4858 list.name = "uapsd_advertisement_enabled";
4859 list.value = enable?"1":"0";
4860
4861 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4862 wifi_hostapdWrite(config_file, &list, 1);
4863 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4864 wifi_reloadAp(apIndex);
4865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4866
4867 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004868}
4869
4870// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
4871INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
4872{
4873 //save config and apply instantly.
4874 return RETURN_ERR;
4875}
4876
4877//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.
4878INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
4879{
4880 //get the running status from driver
4881 if(!output_uint)
4882 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08004883
4884 char output[16]={'\0'};
4885 char config_file[MAX_BUF_SIZE] = {0};
4886
4887 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4888 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
4889 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
4890 else {
4891 int device_num = atoi(output);
4892 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
4893 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
4894 return RETURN_ERR;
4895 }
4896 else {
4897 *output_uint = device_num;
4898 }
4899 }
4900
developer06a01d92022-09-07 16:32:39 +08004901 return RETURN_OK;
4902}
4903
4904INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
4905{
4906 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08004907 char str[MAX_BUF_SIZE]={'\0'};
4908 char cmd[MAX_CMD_SIZE]={'\0'};
4909 struct params params;
4910 char config_file[MAX_BUF_SIZE] = {0};
4911
4912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4913 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
4914 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
4915 return RETURN_ERR;
4916 }
4917 sprintf(str, "%d", number);
4918 params.name = "max_num_sta";
4919 params.value = str;
4920
4921 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
4922 int ret = wifi_hostapdWrite(config_file, &params, 1);
4923 if (ret) {
4924 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
4925 ,__func__, ret);
4926 }
4927
4928 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
4929 if (ret) {
4930 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
4931 ,__func__, ret);
4932 }
4933 wifi_reloadAp(apIndex);
4934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4935
4936 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004937}
4938
4939//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.
4940INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
4941{
4942 //get the current threshold
4943 if(!output_uint)
4944 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08004945 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
4946 if (*output_uint == 0)
4947 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08004948 return RETURN_OK;
4949}
4950
4951INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
4952{
4953 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08004954 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
4955 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004956 return RETURN_ERR;
4957}
4958
4959//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.
4960INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
4961{
4962 if(!output_uint)
4963 return RETURN_ERR;
4964 *output_uint = 3;
4965 return RETURN_OK;
4966}
4967
4968//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
4969INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
4970{
4971 if(!output_uint)
4972 return RETURN_ERR;
4973 *output_uint = 3;
4974 return RETURN_OK;
4975}
4976
4977//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.
4978INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
4979{
4980 if(!output_in_seconds)
4981 return RETURN_ERR;
4982 *output_in_seconds = 0;
4983 return RETURN_OK;
4984}
4985
4986//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
4987INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
4988{
4989 if(!output || apIndex>=MAX_APS)
4990 return RETURN_ERR;
4991 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
4992 snprintf(output, 128, "None,WPA2-Personal");
4993 return RETURN_OK;
4994}
4995
4996//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
4997INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
4998{
4999 char config_file[MAX_BUF_SIZE] = {0};
5000 char buf[32] = {0};
5001 if (!output)
5002 return RETURN_ERR;
5003
5004 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5005 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5006
5007 strcpy(output,"None");//Copying "None" to output string for default case
5008 if((strcmp(buf, "3")==0))
5009 snprintf(output, 32, "WPA-WPA2-Personal");
5010 else if((strcmp(buf, "2")==0))
5011 snprintf(output, 32, "WPA2-Personal");
5012 else if((strcmp(buf, "1")==0))
5013 snprintf(output, 32, "WPA-Personal");
5014 //TODO: need to handle enterprise authmode
5015
5016 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5017 return RETURN_OK;
5018#if 0
5019 //TODO: need to revisit below implementation
5020 char securityType[32], authMode[32];
5021 int enterpriseMode=0;
5022
5023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5024 if(!output)
5025 return RETURN_ERR;
5026
5027 wifi_getApBeaconType(apIndex, securityType);
5028 strcpy(output,"None");//By default, copying "None" to output string
5029 if (strncmp(securityType,"None", strlen("None")) == 0)
5030 return RETURN_OK;
5031
5032 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5033 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5034
5035 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5036 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5037 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5038 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5039 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5040 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5041 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5042
5043 return RETURN_OK;
5044#endif
5045}
5046
5047INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
5048{
5049 char securityType[32];
5050 char authMode[32];
5051
5052 //store settings and wait for wifi up to apply
5053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5054 if(!encMode)
5055 return RETURN_ERR;
5056
5057 printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
5058 if (strcmp(encMode, "None")==0)
5059 {
5060 strcpy(securityType,"None");
5061 strcpy(authMode,"None");
5062 }
5063 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
5064 {
5065 strcpy(securityType,"WPAand11i");
5066 strcpy(authMode,"PSKAuthentication");
5067 }
5068 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
5069 {
5070 strcpy(securityType,"WPAand11i");
5071 strcpy(authMode,"EAPAuthentication");
5072 }
5073 else if (strcmp(encMode, "WPA-Personal")==0)
5074 {
5075 strcpy(securityType,"WPA");
5076 strcpy(authMode,"PSKAuthentication");
5077 }
5078 else if (strcmp(encMode, "WPA-Enterprise")==0)
5079 {
5080 strcpy(securityType,"WPA");
5081 strcpy(authMode,"EAPAuthentication");
5082 }
5083 else if (strcmp(encMode, "WPA2-Personal")==0)
5084 {
5085 strcpy(securityType,"11i");
5086 strcpy(authMode,"PSKAuthentication");
5087 }
5088 else if (strcmp(encMode, "WPA2-Enterprise")==0)
5089 {
5090 strcpy(securityType,"11i");
5091 strcpy(authMode,"EAPAuthentication");
5092 }
5093 else
5094 {
5095 strcpy(securityType,"None");
5096 strcpy(authMode,"None");
5097 }
5098 wifi_setApBeaconType(apIndex, securityType);
5099 wifi_setApBasicAuthenticationMode(apIndex, authMode);
5100 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5101
5102 return RETURN_OK;
5103}
5104
5105
5106//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5107// output_string must be pre-allocated as 64 character string by caller
5108// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5109INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5110{
5111 char buf[16];
5112 char config_file[MAX_BUF_SIZE] = {0};
5113
5114 if(output_string==NULL)
5115 return RETURN_ERR;
5116
5117 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5118 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5119
5120 if(strcmp(buf,"0")==0)
5121 {
5122 printf("wpa_mode is %s ......... \n",buf);
5123 return RETURN_ERR;
5124 }
5125
5126 wifi_dbg_printf("\nFunc=%s\n",__func__);
5127 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5128 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5129 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5130
5131 return RETURN_OK;
5132}
5133
5134// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5135// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5136INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5137{
5138 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5139 struct params params={'\0'};
5140 int ret;
5141 char config_file[MAX_BUF_SIZE] = {0};
5142
5143 if(NULL == preSharedKey)
5144 return RETURN_ERR;
5145
5146 params.name = "wpa_passphrase";
5147
5148 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5149 {
5150 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5151 return RETURN_ERR;
5152 }
5153 params.value = preSharedKey;
5154 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5155 ret = wifi_hostapdWrite(config_file, &params, 1);
5156 if(!ret)
5157 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5158 return ret;
5159 //TODO: call hostapd_cli for dynamic_config_control
5160}
5161
5162//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5163// outputs the passphrase, maximum 63 characters
5164INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5165{
5166 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5167
5168 wifi_dbg_printf("\nFunc=%s\n",__func__);
5169 if (NULL == output_string)
5170 return RETURN_ERR;
5171
5172 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5173 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5174 if(strcmp(buf,"0")==0)
5175 {
5176 printf("wpa_mode is %s ......... \n",buf);
5177 return RETURN_ERR;
5178 }
5179
5180 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5181 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5182
5183 return RETURN_OK;
5184}
5185
5186// sets the passphrase enviornment variable, max 63 characters
5187INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5188{
5189 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5190 struct params params={'\0'};
5191 char config_file[MAX_BUF_SIZE] = {0};
5192 int ret;
5193
5194 if(NULL == passPhrase)
5195 return RETURN_ERR;
5196
5197 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5198 {
5199 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5200 return RETURN_ERR;
5201 }
5202 params.name = "wpa_passphrase";
5203 params.value = passPhrase;
5204 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5205 ret=wifi_hostapdWrite(config_file,&params,1);
5206 if(!ret)
5207 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5208
5209 return ret;
5210}
5211
5212//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.
5213INT wifi_setApSecurityReset(INT apIndex)
5214{
5215 //apply instantly
5216 return RETURN_ERR;
5217}
5218
5219//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).
5220INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5221{
5222 if(!IP_output || !Port_output || !RadiusSecret_output)
5223 return RETURN_ERR;
5224 snprintf(IP_output, 64, "75.56.77.78");
5225 *Port_output = 123;
5226 snprintf(RadiusSecret_output, 64, "12345678");
5227
5228 return RETURN_OK;
5229}
5230
5231INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
5232{
5233 //store the paramters, and apply instantly
5234 return RETURN_ERR;
5235}
5236
5237INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5238{
5239 if(!IP_output || !Port_output || !RadiusSecret_output)
5240 return RETURN_ERR;
5241 snprintf(IP_output, 64, "75.56.77.78");
5242 *Port_output = 123;
5243 snprintf(RadiusSecret_output, 64, "12345678");
5244 return RETURN_OK;
5245}
5246
5247INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
5248{
5249 //store the paramters, and apply instantly
5250 return RETURN_ERR;
5251}
5252
5253//RadiusSettings
5254INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
5255{
5256 if(!output)
5257 return RETURN_ERR;
5258
5259 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
5260 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
5261 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
5262 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
5263 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
5264 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.
5265 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
5266 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
5267 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
5268 //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.
5269
5270 return RETURN_OK;
5271}
5272
5273INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
5274{
5275 //store the paramters, and apply instantly
5276 return RETURN_ERR;
5277}
5278
5279//Device.WiFi.AccessPoint.{i}.WPS.Enable
5280//Enables or disables WPS functionality for this access point.
5281// outputs the WPS enable state of this ap in output_bool
5282INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
5283{
5284 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
5285 if(!output_bool || !(apIndex==0 || apIndex==1))
5286 return RETURN_ERR;
5287 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
5288 _syscmd(cmd, buf, sizeof(buf));
5289 if(strstr(buf, "configured"))
5290 *output_bool=TRUE;
5291 else
5292 *output_bool=FALSE;
5293
5294 return RETURN_OK;
5295}
5296
5297//Device.WiFi.AccessPoint.{i}.WPS.Enable
5298// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
5299INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
5300{
5301 char config_file[MAX_BUF_SIZE] = {0};
5302 struct params params;
5303
5304 if(!(apIndex==0 || apIndex==1))
5305 return RETURN_ERR;
5306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5307 //store the paramters, and wait for wifi up to apply
5308 params.name = "wps_state";
5309 params.value = enable ? "2":"0";
5310
5311 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5312 wifi_hostapdWrite(config_file, &params, 1);
5313 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5314 wifi_reloadAp(apIndex);
5315
5316 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5317 return RETURN_OK;
5318}
5319
5320//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
5321INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
5322{
5323 if(!output)
5324 return RETURN_ERR;
5325 snprintf(output, 128, "PushButton,PIN");
5326 return RETURN_OK;
5327}
5328
5329//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
5330//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.
5331// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
5332INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
5333{
5334 if(!output)
5335 return RETURN_ERR;
5336 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
5337
5338 return RETURN_OK;
5339}
5340
5341//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
5342// 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
5343INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
5344{
5345 //apply instantly. No setting need to be stored.
5346 char methods[MAX_BUF_SIZE], *token, *next_token;
5347 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
5348 struct params params;
5349
5350 if(!methodString || !(apIndex==0 || apIndex==1))
5351 return RETURN_ERR;
5352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5353 //store the paramters, and wait for wifi up to apply
5354
5355 snprintf(methods, sizeof(methods), "%s", methodString);
5356 for(token=methods; *token; token=next_token)
5357 {
5358 strtok_r(token, ",", &next_token);
5359 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
5360 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
5361 else if(*token=='E')
5362 {
5363 if(!strcmp(methods, "Ethernet"))
5364 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
5365 else if(!strcmp(methods, "ExternalNFCToken"))
5366 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
5367 else
5368 printf("%s: Unknown WpsConfigMethod\n", __func__);
5369 }
5370 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
5371 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
5372 else if(*token=='N' && !strcmp(token, "NFCInterface"))
5373 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
5374 else if(*token=='P' )
5375 {
5376 if(!strcmp(token, "PushButton"))
5377 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
5378 else if(!strcmp(token, "PIN"))
5379 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
5380 else
5381 printf("%s: Unknown WpsConfigMethod\n", __func__);
5382 }
5383 else
5384 printf("%s: Unknown WpsConfigMethod\n", __func__);
5385 }
5386 params.name = "config_methods";
5387 params.value = config_methods;
5388 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5389 wifi_hostapdWrite(config_file, &params, 1);
5390 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5391 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5392
5393 return RETURN_OK;
5394}
5395
5396// outputs the pin value, ulong_pin must be allocated by the caller
5397INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
5398{
5399 char buf[MAX_BUF_SIZE] = {0};
5400 char cmd[MAX_CMD_SIZE] = {0};
5401
5402 if(!output_ulong || !(apIndex==0 || apIndex==1))
5403 return RETURN_ERR;
5404 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
5405 _syscmd(cmd, buf, sizeof(buf));
5406 if(strlen(buf) > 0)
5407 *output_ulong=strtoul(buf, NULL, 10);
5408
5409 return RETURN_OK;
5410}
5411
5412// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
5413INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
5414{
5415 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
5416 char ap_pin[16] = {0};
5417 char buf[MAX_BUF_SIZE] = {0};
5418 char config_file[MAX_BUF_SIZE] = {0};
5419 ULONG prev_pin = 0;
5420 struct params params;
5421
5422 if(!(apIndex==0 || apIndex==1))
5423 return RETURN_ERR;
5424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5425 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
5426 params.name = "ap_pin";
5427 params.value = ap_pin;
5428 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5429 wifi_hostapdWrite(config_file, &params, 1);
5430 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5432
5433 return RETURN_OK;
5434}
5435
5436// Output string is either Not configured or Configured, max 32 characters
5437INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
5438{
5439 char cmd[MAX_CMD_SIZE];
5440 char buf[MAX_BUF_SIZE]={0};
5441
5442 if(!output_string || !(apIndex==0 || apIndex==1))
5443 return RETURN_ERR;
5444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5445 snprintf(output_string, 32, "Not configured");
5446 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
5447 _syscmd(cmd, buf, sizeof(buf));
5448
developer348e3d92022-09-13 14:48:41 +08005449 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08005450 snprintf(output_string, 32, "Configured");
5451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5452
5453 return RETURN_OK;
5454}
5455
5456// sets the WPS pin for this AP
5457INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
5458{
5459 char cmd[MAX_CMD_SIZE];
5460 char buf[MAX_BUF_SIZE]={0};
5461 BOOL enable;
5462
5463 if(!(apIndex==0 || apIndex==1))
5464 return RETURN_ERR;
5465 wifi_getApEnable(apIndex, &enable);
5466 if (!enable)
5467 return RETURN_ERR;
5468 wifi_getApWpsEnable(apIndex, &enable);
5469 if (!enable)
5470 return RETURN_ERR;
5471
5472 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
5473 _syscmd(cmd, buf, sizeof(buf));
5474 if((strstr(buf, "OK"))!=NULL)
5475 return RETURN_OK;
5476
5477 return RETURN_ERR;
5478}
5479
5480// This function is called when the WPS push button has been pressed for this AP
5481INT wifi_setApWpsButtonPush(INT apIndex)
5482{
5483 char cmd[MAX_CMD_SIZE];
5484 char buf[MAX_BUF_SIZE]={0};
5485 BOOL enable=FALSE;
5486
5487 if(!(apIndex==0 || apIndex==1))
5488 return RETURN_ERR;
5489 wifi_getApEnable(apIndex, &enable);
5490 if (!enable)
5491 return RETURN_ERR;
5492
5493 wifi_getApWpsEnable(apIndex, &enable);
5494 if (!enable)
5495 return RETURN_ERR;
5496
5497 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
5498 _syscmd(cmd, buf, sizeof(buf));
5499
5500 if((strstr(buf, "OK"))!=NULL)
5501 return RETURN_OK;
5502 return RETURN_ERR;
5503}
5504
5505// cancels WPS mode for this AP
5506INT wifi_cancelApWPS(INT apIndex)
5507{
5508 char cmd[MAX_CMD_SIZE];
5509 char buf[MAX_BUF_SIZE]={0};
5510
5511 if(!(apIndex==0 || apIndex==1))
5512 return RETURN_ERR;
5513 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
5514 _syscmd(cmd,buf, sizeof(buf));
5515
5516 if((strstr(buf, "OK"))!=NULL)
5517 return RETURN_OK;
5518 return RETURN_ERR;
5519}
5520
5521//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
5522//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
5523INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
5524{
5525 FILE *f;
5526 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
5527 char cmd[256], buf[2048];
5528 char *param , *value, *line=NULL;
5529 size_t len = 0;
5530 ssize_t nread;
5531 wifi_associated_dev_t *dev=NULL;
5532
5533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5534 *associated_dev_array = NULL;
5535 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
5536 _syscmd(cmd,buf,sizeof(buf));
5537 *output_array_size = atoi(buf);
5538
5539 if (*output_array_size <= 0)
5540 return RETURN_OK;
5541
5542 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
5543 *associated_dev_array = dev;
5544 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
5545 _syscmd(cmd,buf,sizeof(buf));
5546 f = fopen("/tmp/connected_devices.txt", "r");
5547 if (f==NULL)
5548 {
5549 *output_array_size=0;
5550 return RETURN_ERR;
5551 }
5552 while ((nread = getline(&line, &len, f)) != -1)
5553 {
5554 param = strtok(line,"=");
5555 value = strtok(NULL,"=");
5556
5557 if( strcmp("flags",param) == 0 )
5558 {
5559 value[strlen(value)-1]='\0';
5560 if(strstr (value,"AUTHORIZED") != NULL )
5561 {
5562 dev[auth_temp].cli_AuthenticationState = 1;
5563 dev[auth_temp].cli_Active = 1;
5564 auth_temp++;
5565 read_flag=1;
5566 }
5567 }
5568 if(read_flag==1)
5569 {
5570 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
5571 {
5572 value[strlen(value)-1]='\0';
5573 sscanf(value, "%x:%x:%x:%x:%x:%x",
5574 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
5575 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
5576 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
5577 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
5578 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
5579 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
5580 mac_temp++;
5581 read_flag=0;
5582 }
5583 }
5584 }
5585 *output_array_size = auth_temp;
5586 auth_temp=0;
5587 mac_temp=0;
5588 free(line);
5589 fclose(f);
5590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5591 return RETURN_OK;
5592}
5593
5594#define MACADDRESS_SIZE 6
5595
5596INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
5597{
5598 FILE *fp = NULL;
5599 char str[MAX_BUF_SIZE] = {0};
5600 int wificlientindex = 0 ;
5601 int count = 0;
5602 int signalstrength = 0;
5603 int arr[MACADDRESS_SIZE] = {0};
5604 unsigned char mac[MACADDRESS_SIZE] = {0};
5605 UINT wifi_count = 0;
5606 char virtual_interface_name[MAX_BUF_SIZE] = {0};
5607 char pipeCmd[MAX_CMD_SIZE] = {0};
5608
5609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5610 *output_array_size = 0;
5611 *associated_dev_array = NULL;
5612
5613 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
5614 fp = popen(pipeCmd, "r");
5615 if (fp == NULL)
5616 {
5617 printf("Failed to run command inside function %s\n",__FUNCTION__ );
5618 return RETURN_ERR;
5619 }
5620
5621 /* Read the output a line at a time - output it. */
5622 fgets(str, sizeof(str)-1, fp);
5623 wifi_count = (unsigned int) atoi ( str );
5624 *output_array_size = wifi_count;
5625 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
5626 pclose(fp);
5627
5628 if(wifi_count == 0)
5629 {
5630 return RETURN_OK;
5631 }
5632 else
5633 {
5634 wifi_associated_dev3_t* temp = NULL;
5635 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
5636 if(temp == NULL)
5637 {
5638 printf("Error Statement. Insufficient memory \n");
5639 return RETURN_ERR;
5640 }
5641
5642 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
5643 system(pipeCmd);
5644 memset(pipeCmd,0,sizeof(pipeCmd));
5645 if(apIndex == 0)
5646 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
5647 else if(apIndex == 1)
5648 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
5649 system(pipeCmd);
5650
5651 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
5652 if(fp == NULL)
5653 {
5654 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
5655 return RETURN_ERR;
5656 }
5657 fclose(fp);
5658
5659 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
5660 fp = popen(pipeCmd, "r");
5661 if(fp)
5662 {
5663 for(count =0 ; count < wifi_count; count++)
5664 {
5665 fgets(str, MAX_BUF_SIZE, fp);
5666 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
5667 {
5668 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
5669 {
5670 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
5671
5672 }
5673 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
5674 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]);
5675 }
5676 temp[count].cli_AuthenticationState = 1; //TODO
5677 temp[count].cli_Active = 1; //TODO
5678 }
5679 pclose(fp);
5680 }
5681
5682 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
5683 fp = popen(pipeCmd, "r");
5684 if(fp)
5685 {
5686 pclose(fp);
5687 }
5688 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
5689 if(fp)
5690 {
5691 for(count =0 ; count < wifi_count ;count++)
5692 {
5693 fgets(str, MAX_BUF_SIZE, fp);
5694 signalstrength = atoi(str);
5695 temp[count].cli_SignalStrength = signalstrength;
5696 temp[count].cli_RSSI = signalstrength;
5697 temp[count].cli_SNR = signalstrength + 95;
5698 }
5699 pclose(fp);
5700 }
5701
5702
5703 if((apIndex == 0) || (apIndex == 4))
5704 {
5705 for(count =0 ; count < wifi_count ;count++)
5706 {
5707 strcpy(temp[count].cli_OperatingStandard,"g");
5708 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
5709 }
5710
5711 //BytesSent
5712 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
5713 fp = popen(pipeCmd, "r");
5714 if(fp)
5715 {
5716 pclose(fp);
5717 }
5718 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
5719 if(fp)
5720 {
5721 for (count = 0; count < wifi_count; count++)
5722 {
5723 fgets(str, MAX_BUF_SIZE, fp);
5724 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
5725 }
5726 pclose(fp);
5727 }
5728
5729 //BytesReceived
5730 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
5731 fp = popen(pipeCmd, "r");
5732 if (fp)
5733 {
5734 pclose(fp);
5735 }
5736 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
5737 if (fp)
5738 {
5739 for (count = 0; count < wifi_count; count++)
5740 {
5741 fgets(str, MAX_BUF_SIZE, fp);
5742 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
5743 }
5744 pclose(fp);
5745 }
5746
5747 //PacketsSent
5748 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
5749 fp = popen(pipeCmd, "r");
5750 if (fp)
5751 {
5752 pclose(fp);
5753 }
5754
5755 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
5756 if (fp)
5757 {
5758 for (count = 0; count < wifi_count; count++)
5759 {
5760 fgets(str, MAX_BUF_SIZE, fp);
5761 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
5762 }
5763 pclose(fp);
5764 }
5765
5766 //PacketsReceived
5767 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
5768 fp = popen(pipeCmd, "r");
5769 if (fp)
5770 {
5771 pclose(fp);
5772 }
5773 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
5774 if (fp)
5775 {
5776 for (count = 0; count < wifi_count; count++)
5777 {
5778 fgets(str, MAX_BUF_SIZE, fp);
5779 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
5780 }
5781 pclose(fp);
5782 }
5783
5784 //ErrorsSent
5785 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
5786 fp = popen(pipeCmd, "r");
5787 if (fp)
5788 {
5789 pclose(fp);
5790 }
5791 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
5792 if (fp)
5793 {
5794 for (count = 0; count < wifi_count; count++)
5795 {
5796 fgets(str, MAX_BUF_SIZE, fp);
5797 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
5798 }
5799 pclose(fp);
5800 }
5801
5802 //ErrorsSent
5803 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
5804 fp = popen(pipeCmd, "r");
5805 if (fp)
5806 {
5807 pclose(fp);
5808 }
5809 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
5810 if (fp)
5811 {
5812 for (count = 0; count < wifi_count; count++)
5813 {
5814 fgets(str, MAX_BUF_SIZE, fp);
5815 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
5816 }
5817 pclose(fp);
5818 }
5819
5820 //LastDataDownlinkRate
5821 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
5822 fp = popen(pipeCmd, "r");
5823 if (fp)
5824 {
5825 pclose(fp);
5826 }
5827 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
5828 if (fp)
5829 {
5830 for (count = 0; count < wifi_count; count++)
5831 {
5832 fgets(str, MAX_BUF_SIZE, fp);
5833 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
5834 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
5835 }
5836 pclose(fp);
5837 }
5838
5839 //LastDataUplinkRate
5840 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
5841 fp = popen(pipeCmd, "r");
5842 if (fp)
5843 {
5844 pclose(fp);
5845 }
5846 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
5847 if (fp)
5848 {
5849 for (count = 0; count < wifi_count; count++)
5850 {
5851 fgets(str, MAX_BUF_SIZE, fp);
5852 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
5853 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
5854 }
5855 pclose(fp);
5856 }
5857
5858 }
5859 else if ((apIndex == 1) || (apIndex == 5))
5860 {
5861 for (count = 0; count < wifi_count; count++)
5862 {
5863 strcpy(temp[count].cli_OperatingStandard, "a");
5864 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
5865 temp[count].cli_BytesSent = 0;
5866 temp[count].cli_BytesReceived = 0;
5867 temp[count].cli_LastDataUplinkRate = 0;
5868 temp[count].cli_LastDataDownlinkRate = 0;
5869 temp[count].cli_PacketsSent = 0;
5870 temp[count].cli_PacketsReceived = 0;
5871 temp[count].cli_ErrorsSent = 0;
5872 }
5873 }
5874
5875 for (count = 0; count < wifi_count; count++)
5876 {
5877 temp[count].cli_Retransmissions = 0;
5878 temp[count].cli_DataFramesSentAck = 0;
5879 temp[count].cli_DataFramesSentNoAck = 0;
5880 temp[count].cli_MinRSSI = 0;
5881 temp[count].cli_MaxRSSI = 0;
5882 strncpy(temp[count].cli_InterferenceSources, "", 64);
5883 memset(temp[count].cli_IPAddress, 0, 64);
5884 temp[count].cli_RetransCount = 0;
5885 temp[count].cli_FailedRetransCount = 0;
5886 temp[count].cli_RetryCount = 0;
5887 temp[count].cli_MultipleRetryCount = 0;
5888 }
5889 *associated_dev_array = temp;
5890 }
5891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5892 return RETURN_OK;
5893}
5894
5895int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
5896{
5897 FILE *fp = NULL;
5898 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
5899 char cmd[MAX_CMD_SIZE];
5900 int count = 0;
5901
5902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5903 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
5904 fp = popen(cmd,"r");
5905 if(fp == NULL)
5906 {
5907 printf("Failed to run command in Function %s\n",__FUNCTION__);
5908 return 0;
5909 }
5910 if(fgets(path, sizeof(path)-1, fp) != NULL)
5911 {
5912 for(count=0;path[count]!='\n';count++)
5913 status[count]=path[count];
5914 status[count]='\0';
5915 }
5916 strcpy(wifi_status,status);
5917 pclose(fp);
5918 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5919 return RETURN_OK;
5920}
5921
5922/* #define HOSTAPD_STA_PARAM_ENTRIES 29
5923struct hostapd_sta_param {
5924 char key[50];
5925 char value[100];
5926}
5927
5928static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
5929 int i = 0;
5930
5931 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
5932 if (strncmp(params[i].key,key,50) == 0){
5933 return &params[i].value;
5934 }
5935 i++;
5936 }
5937 return NULL;
5938
5939} */
5940
5941static unsigned int count_occurences(const char *buf, const char *word)
5942{
5943 unsigned int n = 0;
5944 char *ptr = strstr(buf, word);
5945
5946 while (ptr++) {
5947 n++;
5948 ptr = strstr(ptr, word);
5949 }
5950
5951 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
5952 return n;
5953}
5954
5955static const char *get_line_from_str_buf(const char *buf, char *line)
5956{
5957 int i;
5958 int n = strlen(buf);
5959
5960 for (i = 0; i < n; i++) {
5961 line[i] = buf[i];
5962 if (buf[i] == '\n') {
5963 line[i] = '\0';
5964 return &buf[i + 1];
5965 }
5966 }
5967
5968 return NULL;
5969}
5970
5971INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
5972{
5973 unsigned int assoc_cnt = 0;
5974 char interface_name[50] = {0};
5975 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
5976 char cmd[MAX_CMD_SIZE] = {'\0'};
5977 char line[256] = {'\0'};
5978 int i = 0;
5979 int ret = 0;
5980 const char *ptr = NULL;
5981 char *key = NULL;
5982 char *val = NULL;
5983 wifi_associated_dev3_t *temp = NULL;
5984 int rssi;
5985
5986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5987
5988 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
5989 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
5990 return RETURN_ERR;
5991 }
5992
5993 // Example filtered output of 'iw dev' command:
5994 // Station 0a:69:72:10:d2:fa (on wifi0)
5995 // signal avg:-67 [-71, -71] dBm
5996 // Station 28:c2:1f:25:5f:99 (on wifi0)
5997 // signal avg:-67 [-71, -70] dBm
5998 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
5999 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
6000 return RETURN_ERR;
6001 }
6002
6003 ret = _syscmd(cmd, buf, sizeof(buf));
6004 if (ret == RETURN_ERR) {
6005 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
6006 return RETURN_ERR;
6007 }
6008
6009 *output_array_size = count_occurences(buf, "Station");
6010 if (*output_array_size == 0) return RETURN_OK;
6011
6012 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
6013 if (temp == NULL) {
6014 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
6015 return RETURN_ERR;
6016 }
6017 *associated_dev_array = temp;
6018
6019 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
6020 ptr = get_line_from_str_buf(buf, line);
6021 i = -1;
6022 while (ptr) {
6023 if (strstr(line, "Station")) {
6024 i++;
6025 key = strtok(line, " ");
6026 val = strtok(NULL, " ");
6027 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
6028 &temp[i].cli_MACAddress[0],
6029 &temp[i].cli_MACAddress[1],
6030 &temp[i].cli_MACAddress[2],
6031 &temp[i].cli_MACAddress[3],
6032 &temp[i].cli_MACAddress[4],
6033 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
6034 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
6035 free(*associated_dev_array);
6036 return RETURN_ERR;
6037 }
6038 }
6039 else if (i < 0) {
6040 ptr = get_line_from_str_buf(ptr, line);
6041 continue; // We didn't detect 'station' entry yet
6042 }
6043 else if (strstr(line, "signal avg")) {
6044 key = strtok(line, ":");
6045 val = strtok(NULL, " ");
6046 if (sscanf(val, "%d", &rssi) <= 0 ) {
6047 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
6048 free(*associated_dev_array);
6049 return RETURN_ERR;
6050 }
6051 temp[i].cli_RSSI = rssi;
6052 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
6053 }
6054 // Here other fields can be parsed if added to filter of 'iw dev' command
6055
6056 ptr = get_line_from_str_buf(ptr, line);
6057 };
6058
6059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6060
6061 return RETURN_OK;
6062}
6063
6064#if 0
6065//To-do
6066INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6067{
6068 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6069
6070 //Using different approach to get required WiFi Parameters from system available commands
6071#if 0
6072 FILE *f;
6073 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6074 char cmd[256], buf[2048];
6075 char *param , *value, *line=NULL;
6076 size_t len = 0;
6077 ssize_t nread;
6078 wifi_associated_dev3_t *dev=NULL;
6079 *associated_dev_array = NULL;
6080 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6081 _syscmd(cmd,buf,sizeof(buf));
6082 *output_array_size = atoi(buf);
6083
6084 if (*output_array_size <= 0)
6085 return RETURN_OK;
6086
6087 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
6088 *associated_dev_array = dev;
6089 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
6090 _syscmd(cmd,buf,sizeof(buf));
6091 f = fopen("/tmp/connected_devices.txt", "r");
6092 if (f==NULL)
6093 {
6094 *output_array_size=0;
6095 return RETURN_ERR;
6096 }
6097 while ((nread = getline(&line, &len, f)) != -1)
6098 {
6099 param = strtok(line,"=");
6100 value = strtok(NULL,"=");
6101
6102 if( strcmp("flags",param) == 0 )
6103 {
6104 value[strlen(value)-1]='\0';
6105 if(strstr (value,"AUTHORIZED") != NULL )
6106 {
6107 dev[auth_temp].cli_AuthenticationState = 1;
6108 dev[auth_temp].cli_Active = 1;
6109 auth_temp++;
6110 read_flag=1;
6111 }
6112 }
6113 if(read_flag==1)
6114 {
6115 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6116 {
6117 value[strlen(value)-1]='\0';
6118 sscanf(value, "%x:%x:%x:%x:%x:%x",
6119 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6120 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6121 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6122 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6123 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6124 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6125
6126 }
6127 else if( strcmp("rx_packets",param) == 0 )
6128 {
6129 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
6130 }
6131
6132 else if( strcmp("tx_packets",param) == 0 )
6133 {
6134 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
6135 }
6136
6137 else if( strcmp("rx_bytes",param) == 0 )
6138 {
6139 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
6140 }
6141
6142 else if( strcmp("tx_bytes",param) == 0 )
6143 {
6144 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
6145 mac_temp++;
6146 read_flag=0;
6147 }
6148 }
6149 }
6150
6151 *output_array_size = auth_temp;
6152 auth_temp=0;
6153 mac_temp=0;
6154 free(line);
6155 fclose(f);
6156#endif
6157 char interface_name[MAX_BUF_SIZE] = {0};
6158 char wifi_status[MAX_BUF_SIZE] = {0};
6159 char hostapdconf[MAX_BUF_SIZE] = {0};
6160
6161 wifi_associated_dev3_t *dev_array = NULL;
6162 ULONG wifi_count = 0;
6163
6164 *associated_dev_array = NULL;
6165 *output_array_size = 0;
6166
6167 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
6168 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
6169 {
6170 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
6171
6172 GetInterfaceName(interface_name, hostapdconf);
6173
6174 if(strlen(interface_name) > 1)
6175 {
6176 wifihal_interfacestatus(wifi_status,interface_name);
6177 if(strcmp(wifi_status,"RUNNING") == 0)
6178 {
6179 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
6180
6181 *associated_dev_array = dev_array;
6182 *output_array_size = wifi_count;
6183 }
6184 else
6185 {
6186 *associated_dev_array = NULL;
6187 }
6188 }
6189 }
6190
6191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6192 return RETURN_OK;
6193}
6194#endif
6195
6196/* getIPAddress function */
6197/**
6198* @description Returning IpAddress of the Matched String
6199*
6200* @param
6201* @str Having MacAddress
6202* @ipaddr Having ipaddr
6203* @return The status of the operation
6204* @retval RETURN_OK if successful
6205* @retval RETURN_ERR if any error is detected
6206*
6207*/
6208
6209INT getIPAddress(char *str,char *ipaddr)
6210{
6211 FILE *fp = NULL;
6212 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
6213 int LeaseTime = 0,ret = 0;
6214 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
6215 {
6216 return RETURN_ERR;
6217 }
6218
6219 while ( fgets(buf, sizeof(buf), fp)!= NULL )
6220 {
6221 /*
6222 Sample:sss
6223 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
6224 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
6225 */
6226 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
6227 &(LeaseTime),
6228 phyAddr,
6229 ipAddr,
6230 hostName
6231 );
6232 if(ret != 4)
6233 continue;
6234 if(strcmp(str,phyAddr) == 0)
6235 strcpy(ipaddr,ipAddr);
6236 }
6237 return RETURN_OK;
6238}
6239
6240/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
6241/**
6242* @description Returning Inactive wireless connected clients informations
6243*
6244* @param
6245* @filename Holding private_wifi 2g/5g content files
6246* @associated_dev_array Having inactiv wireless clients informations
6247* @output_array_size Returning Inactive wireless counts
6248* @return The status of the operation
6249* @retval RETURN_OK if successful
6250* @retval RETURN_ERR if any error is detected
6251*
6252*/
6253
6254INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6255{
6256 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6257 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
6258 FILE *fp = NULL;
6259 int arr[MACADDRESS_SIZE] = {0};
6260 unsigned char mac[MACADDRESS_SIZE] = {0};
6261 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
6262 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
6263 fp = popen(buf,"r");
6264 if(fp == NULL)
6265 return RETURN_ERR;
6266 else
6267 {
6268 fgets(path,sizeof(path),fp);
6269 maccount = atoi(path);
6270 }
6271 pclose(fp);
6272 *output_array_size = maccount;
6273 wifi_associated_dev3_t* temp = NULL;
6274 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
6275 *associated_dev_array = temp;
6276 if(temp == NULL)
6277 {
6278 printf("Error Statement. Insufficient memory \n");
6279 return RETURN_ERR;
6280 }
6281 memset(buf,0,sizeof(buf));
6282 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
6283 fp = popen(buf,"r");
6284 for(count = 0; count < maccount ; count++)
6285 {
6286 fgets(path,sizeof(path),fp);
6287 for(i = 0; path[i]!='\n';i++)
6288 str[i]=path[i];
6289 str[i]='\0';
6290 getIPAddress(str,ipaddr);
6291 memset(buf,0,sizeof(buf));
6292 if(strlen(ipaddr) > 0)
6293 {
6294 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
6295 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
6296 {
6297 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6298 {
6299 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6300 {
6301 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6302
6303 }
6304 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6305 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]);
6306 }
6307 temp[count].cli_AuthenticationState = 0; //TODO
6308 temp[count].cli_Active = 0; //TODO
6309 temp[count].cli_SignalStrength = 0;
6310 }
6311 else //Active wireless clients info
6312 {
6313 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6314 {
6315 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6316 {
6317 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6318
6319 }
6320 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6321 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]);
6322 }
6323 temp[count].cli_Active = 1;
6324 }
6325 }
6326 memset(ipaddr,0,sizeof(ipaddr));
6327 }
6328 pclose(fp);
6329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6330 return RETURN_OK;
6331}
6332//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
6333//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
6334//To get Band Steering Capability
6335INT wifi_getBandSteeringCapability(BOOL *support)
6336{
6337 *support = FALSE;
6338 return RETURN_OK;
6339}
6340
6341
6342//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
6343//To get Band Steering enable status
6344INT wifi_getBandSteeringEnable(BOOL *enable)
6345{
6346 *enable = FALSE;
6347 return RETURN_OK;
6348}
6349
6350//To turn on/off Band steering
6351INT wifi_setBandSteeringEnable(BOOL enable)
6352{
6353 return RETURN_OK;
6354}
6355
6356//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
6357//To get Band Steering AP group
6358INT wifi_getBandSteeringApGroup(char *output_ApGroup)
6359{
6360 if (NULL == output_ApGroup)
6361 return RETURN_ERR;
6362
6363 strcpy(output_ApGroup, "1,2");
6364 return RETURN_OK;
6365}
6366
6367//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
6368//to set and read the band steering BandUtilizationThreshold parameters
6369INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
6370{
6371 return RETURN_ERR;
6372}
6373
6374INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
6375{
6376 return RETURN_ERR;
6377}
6378
6379//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
6380//to set and read the band steering RSSIThreshold parameters
6381INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
6382{
6383 return RETURN_ERR;
6384}
6385
6386INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
6387{
6388 return RETURN_ERR;
6389}
6390
6391
6392//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
6393//to set and read the band steering physical modulation rate threshold parameters
6394INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
6395{
6396 //If chip is not support, return -1
6397 return RETURN_ERR;
6398}
6399
6400INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
6401{
6402 //If chip is not support, return -1
6403 return RETURN_ERR;
6404}
6405
6406//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
6407//to set and read the inactivity time (in seconds) for steering under overload condition
6408INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
6409{
6410 return RETURN_ERR;
6411}
6412
6413INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
6414{
6415 return RETURN_ERR;
6416}
6417
6418//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
6419//to set and read the inactivity time (in seconds) for steering under Idle condition
6420INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
6421{
6422 return RETURN_ERR;
6423}
6424
6425INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
6426{
6427 return RETURN_ERR;
6428}
6429
6430//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
6431//pClientMAC[64]
6432//pSourceSSIDIndex[64]
6433//pDestSSIDIndex[64]
6434//pSteeringReason[256]
6435INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
6436{
6437 //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
6438 *pSteeringTime=time(NULL);
6439 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
6440 return RETURN_OK;
6441}
6442
6443INT wifi_ifConfigDown(INT apIndex)
6444{
6445 INT status = RETURN_OK;
6446 char cmd[64];
6447
6448 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
6449 printf("%s: %s\n", __func__, cmd);
6450 system(cmd);
6451
6452 return status;
6453}
6454
6455INT wifi_ifConfigUp(INT apIndex)
6456{
6457 char cmd[128];
6458 char buf[1024];
6459
6460 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
6461 _syscmd(cmd, buf, sizeof(buf));
6462 return 0;
6463}
6464
6465//>> Deprecated. Replace with wifi_applyRadioSettings
6466INT wifi_pushBridgeInfo(INT apIndex)
6467{
6468 char ip[32];
6469 char subnet[32];
6470 char bridge[32];
6471 int vlanId;
6472 char cmd[128];
6473 char buf[1024];
6474
6475 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
6476 wifi_getApVlanID(apIndex,&vlanId);
6477
6478 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
6479 _syscmd(cmd,buf, sizeof(buf));
6480
6481 return 0;
6482}
6483
6484INT wifi_pushChannel(INT radioIndex, UINT channel)
6485{
6486 char cmd[128];
6487 char buf[1024];
6488 int apIndex;
6489
6490 apIndex=(radioIndex==0)?0:1;
6491 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
6492 _syscmd(cmd,buf, sizeof(buf));
6493
6494 return 0;
6495}
6496
6497INT wifi_pushChannelMode(INT radioIndex)
6498{
6499 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
6500 return RETURN_ERR;
6501}
6502
6503INT wifi_pushDefaultValues(INT radioIndex)
6504{
6505 //Apply Comcast specified default radio settings instantly
6506 //AMPDU=1
6507 //AMPDUFrames=32
6508 //AMPDULim=50000
6509 //txqueuelen=1000
6510
6511 return RETURN_ERR;
6512}
6513
6514INT wifi_pushTxChainMask(INT radioIndex)
6515{
6516 //Apply default TxChainMask instantly
6517 return RETURN_ERR;
6518}
6519
6520INT wifi_pushRxChainMask(INT radioIndex)
6521{
6522 //Apply default RxChainMask instantly
6523 return RETURN_ERR;
6524}
6525
6526INT wifi_pushSSID(INT apIndex, CHAR *ssid)
6527{
6528 INT status;
6529
6530 status = wifi_setSSIDName(apIndex,ssid);
6531 wifi_setApEnable(apIndex,FALSE);
6532 wifi_setApEnable(apIndex,TRUE);
6533
6534 return status;
6535}
6536
6537INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
6538{
6539 //Apply default Ssid Advertisement instantly
6540 return RETURN_ERR;
6541}
6542
6543INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
6544{
6545 INT status = RETURN_ERR;
6546 *output = 0;
6547 return RETURN_ERR;
6548}
6549
6550INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
6551{
6552 return RETURN_OK;
6553}
6554
6555INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
6556{
6557 return RETURN_OK;
6558}
6559
6560//To-do
6561INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
6562{
developereb199ae2022-09-13 14:04:27 +08006563 char output[16]={'\0'};
6564 char config_file[MAX_BUF_SIZE] = {0};
6565
6566 if (!output_string)
6567 return RETURN_ERR;
6568
6569 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6570 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
6571
6572 if (strlen(output) == 0)
6573 snprintf(output_string, 64, "Disabled");
6574 else if (strncmp(output, "0", 1) == 0)
6575 snprintf(output_string, 64, "Disabled");
6576 else if (strncmp(output, "1", 1) == 0)
6577 snprintf(output_string, 64, "Optional");
6578 else if (strncmp(output, "2", 1) == 0)
6579 snprintf(output_string, 64, "Required");
6580 else {
6581 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
6582 return RETURN_ERR;
6583 }
6584
6585 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08006586 return RETURN_OK;
6587}
6588INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
6589{
developereb199ae2022-09-13 14:04:27 +08006590 char str[MAX_BUF_SIZE]={'\0'};
6591 char cmd[MAX_CMD_SIZE]={'\0'};
6592 struct params params;
6593 char config_file[MAX_BUF_SIZE] = {0};
6594
6595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6596 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
6597 return RETURN_ERR;
6598
6599 params.name = "ieee80211w";
6600 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
6601 params.value = "0";
6602 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
6603 params.value = "1";
6604 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
6605 params.value = "2";
6606 else{
6607 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
6608 return RETURN_ERR;
6609 }
6610 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6611 wifi_hostapdWrite(config_file, &params, 1);
6612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006613 return RETURN_OK;
6614}
6615INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
6616{
6617 char output[16]={'\0'};
6618 char config_file[MAX_BUF_SIZE] = {0};
6619
6620 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6621 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
6622 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
6623
6624 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
6625 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
6626
6627 return RETURN_OK;
6628}
6629
6630INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
6631{
6632 return RETURN_OK;
6633}
6634
6635INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
6636{
6637 return RETURN_OK;
6638}
6639
6640INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
6641{
6642 return RETURN_OK;
6643}
6644
6645INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
6646{
6647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6648 char config_file[MAX_BUF_SIZE] = {0};
6649
6650 if (NULL == output)
6651 return RETURN_ERR;
6652 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
6653 wifi_hostapdRead(config_file,"hw_mode",output,64);
6654
6655 if(strcmp(output,"b")==0)
6656 sprintf(output, "%s", "1,2,5.5,11");
6657 else if (strcmp(output,"a")==0)
6658 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
6659 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
6660 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
6661
6662 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6663 return RETURN_OK;
6664}
6665
6666INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
6667{
6668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6669 char *temp;
6670 char temp_output[128];
6671 char temp_TransmitRates[128];
6672 char config_file[MAX_BUF_SIZE] = {0};
6673
6674 if (NULL == output)
6675 return RETURN_ERR;
6676
6677 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
6678 wifi_hostapdRead(config_file,"supported_rates",output,64);
6679
6680 strcpy(temp_TransmitRates,output);
6681 strcpy(temp_output,"");
6682 temp = strtok(temp_TransmitRates," ");
6683 while(temp!=NULL)
6684 {
6685 temp[strlen(temp)-1]=0;
6686 if((temp[0]=='5') && (temp[1]=='\0'))
6687 {
6688 temp="5.5";
6689 }
6690 strcat(temp_output,temp);
6691 temp = strtok(NULL," ");
6692 if(temp!=NULL)
6693 {
6694 strcat(temp_output,",");
6695 }
6696 }
6697 strcpy(output,temp_output);
6698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6699
6700 return RETURN_OK;
6701}
6702
6703INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
6704{
6705 return RETURN_OK;
6706}
6707
6708
6709INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
6710{
6711 int i=0;
6712 char *temp;
6713 char temp1[128];
6714 char temp_output[128];
6715 char temp_TransmitRates[128];
6716 struct params params={'\0'};
6717 char config_file[MAX_BUF_SIZE] = {0};
6718
6719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6720 if(NULL == output)
6721 return RETURN_ERR;
6722
6723 strcpy(temp_TransmitRates,output);
6724
6725 for(i=0;i<strlen(temp_TransmitRates);i++)
6726 {
6727 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
6728 {
6729 continue;
6730 }
6731 else
6732 {
6733 return RETURN_ERR;
6734 }
6735 }
6736 strcpy(temp_output,"");
6737 temp = strtok(temp_TransmitRates," ");
6738 while(temp!=NULL)
6739 {
6740 strcpy(temp1,temp);
6741 if(wlanIndex==1)
6742 {
6743 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
6744 {
6745 return RETURN_ERR;
6746 }
6747 }
6748
6749 if(strcmp(temp,"5.5")==0)
6750 {
6751 strcpy(temp1,"55");
6752 }
6753 else
6754 {
6755 strcat(temp1,"0");
6756 }
6757 strcat(temp_output,temp1);
6758 temp = strtok(NULL," ");
6759 if(temp!=NULL)
6760 {
6761 strcat(temp_output," ");
6762 }
6763 }
6764 strcpy(output,temp_output);
6765
6766
6767 params.name = "supported_rates";
6768 params.value = output;
6769
6770 wifi_dbg_printf("\n%s:",__func__);
6771 wifi_dbg_printf("params.value=%s\n",params.value);
6772 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
6773 wifi_hostapdWrite(config_file,&params,1);
6774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6775
6776 return RETURN_OK;
6777}
6778
6779
6780static char *sncopy(char *dst, int dst_sz, const char *src)
6781{
6782 if (src && dst && dst_sz > 0) {
6783 strncpy(dst, src, dst_sz);
6784 dst[dst_sz - 1] = '\0';
6785 }
6786 return dst;
6787}
6788
6789static int util_get_sec_chan_offset(int channel, const char* ht_mode)
6790{
6791 if (0 == strcmp(ht_mode, "HT40") ||
6792 0 == strcmp(ht_mode, "HT80") ||
6793 0 == strcmp(ht_mode, "HT160")) {
6794 switch (channel) {
6795 case 1 ... 7:
6796 case 36:
6797 case 44:
6798 case 52:
6799 case 60:
6800 case 100:
6801 case 108:
6802 case 116:
6803 case 124:
6804 case 132:
6805 case 140:
6806 case 149:
6807 case 157:
6808 return 1;
6809 case 8 ... 13:
6810 case 40:
6811 case 48:
6812 case 56:
6813 case 64:
6814 case 104:
6815 case 112:
6816 case 120:
6817 case 128:
6818 case 136:
6819 case 144:
6820 case 153:
6821 case 161:
6822 return -1;
6823 default:
6824 return -EINVAL;
6825 }
6826 }
6827
6828 return -EINVAL;
6829}
6830
6831static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
6832{
6833 if (NULL == hw_mode) return;
6834
6835 if (0 == strcmp(hw_mode, "ac"))
6836 sncopy(bw_mode, bw_mode_len, "ht vht");
6837
6838 if (0 == strcmp(hw_mode, "n"))
6839 sncopy(bw_mode, bw_mode_len, "ht");
6840
6841 return;
6842}
6843
6844static int util_chan_to_freq(int chan)
6845{
6846 if (chan == 14)
6847 return 2484;
6848 else if (chan < 14)
6849 return 2407 + chan * 5;
6850 else if (chan >= 182 && chan <= 196)
6851 return 4000 + chan * 5;
6852 else
6853 return 5000 + chan * 5;
6854 return 0;
6855}
6856
6857const int *util_unii_5g_chan2list(int chan, int width)
6858{
6859 static const int lists[] = {
6860 // <width>, <chan1>, <chan2>..., 0,
6861 20, 36, 0,
6862 20, 40, 0,
6863 20, 44, 0,
6864 20, 48, 0,
6865 20, 52, 0,
6866 20, 56, 0,
6867 20, 60, 0,
6868 20, 64, 0,
6869 20, 100, 0,
6870 20, 104, 0,
6871 20, 108, 0,
6872 20, 112, 0,
6873 20, 116, 0,
6874 20, 120, 0,
6875 20, 124, 0,
6876 20, 128, 0,
6877 20, 132, 0,
6878 20, 136, 0,
6879 20, 140, 0,
6880 20, 144, 0,
6881 20, 149, 0,
6882 20, 153, 0,
6883 20, 157, 0,
6884 20, 161, 0,
6885 20, 165, 0,
6886 40, 36, 40, 0,
6887 40, 44, 48, 0,
6888 40, 52, 56, 0,
6889 40, 60, 64, 0,
6890 40, 100, 104, 0,
6891 40, 108, 112, 0,
6892 40, 116, 120, 0,
6893 40, 124, 128, 0,
6894 40, 132, 136, 0,
6895 40, 140, 144, 0,
6896 40, 149, 153, 0,
6897 40, 157, 161, 0,
6898 80, 36, 40, 44, 48, 0,
6899 80, 52, 56, 60, 64, 0,
6900 80, 100, 104, 108, 112, 0,
6901 80, 116, 120, 124, 128, 0,
6902 80, 132, 136, 140, 144, 0,
6903 80, 149, 153, 157, 161, 0,
6904 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
6905 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
6906 -1 // final delimiter
6907 };
6908 const int *start;
6909 const int *p;
6910
6911 for (p = lists; *p != -1; p++) {
6912 if (*p == width) {
6913 for (start = ++p; *p != 0; p++) {
6914 if (*p == chan)
6915 return start;
6916 }
6917 }
6918 // move to the end of channel list of given width
6919 while (*p != 0) {
6920 p++;
6921 }
6922 }
6923
6924 return NULL;
6925}
6926
6927static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
6928{
6929 if (NULL == ht_mode)
6930 return 0;
6931
6932 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
6933 const int *chans = util_unii_5g_chan2list(channel, width);
6934 int sum = 0;
6935 int cnt = 0;
6936
6937 if (NULL == chans)
6938 return 0;
6939
6940 while (*chans) {
6941 sum += *chans;
6942 cnt++;
6943 chans++;
6944 }
6945 return sum / cnt;
6946}
6947
6948static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
6949{
6950 BOOL onlyG, onlyN, onlyA;
6951 CHAR tmp[64];
6952 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
6953 if (ret == RETURN_OK) {
6954 sncopy(hw_mode, hw_mode_size, tmp);
6955 }
6956 return ret;
6957}
6958
6959INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
6960{
6961 // Sample commands:
6962 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
6963 // hostapd_cli -i wifi0 chan_switch 30 2437
6964 char cmd[MAX_CMD_SIZE] = {0};
6965 char buf[MAX_BUF_SIZE] = {0};
6966 int freq = 0, ret = 0;
6967 char center_freq1_str[32] = ""; // center_freq1=%d
6968 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
6969 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
6970 char hw_mode[16] = ""; // n|ac
6971 char bw_mode[16] = ""; // ht|ht vht
6972 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
6973 int sec_chan_offset;
6974 int width;
6975
6976 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6977
6978 freq = util_chan_to_freq(channel);
6979
6980 // Get radio mode HT20|HT40|HT80 etc.
6981 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
6982 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
6983 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
6984 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
6985 if (sec_chan_offset != -EINVAL)
6986 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
6987
6988
6989 // Provide bandwith if specified
6990 if (channel_width_MHz > 20) {
6991 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
6992 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
6993 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
6994
6995 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
6996 }
6997
6998 int center_chan = 0;
6999 if (channel_width_MHz > 20) {
7000 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
7001 if (center_chan > 0) {
7002 int center_freq1 = util_chan_to_freq(center_chan);
7003 if (center_freq1)
7004 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
7005 }
7006 }
7007
7008 {
7009 // Only the first AP, other are hanging on the same radio
7010 int apIndex = radioIndex;
7011 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
7012 AP_PREFIX, apIndex, csa_beacon_count, freq,
7013 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
7014 wifi_dbg_printf("execute: '%s'\n", cmd);
7015 ret = _syscmd(cmd, buf, sizeof(buf));
7016 }
7017
7018 wifi_setRadioChannel(radioIndex, channel);
7019
7020 char *ext_str = "None";
7021 if (sec_chan_offset == 1) ext_str = "Above";
7022 else if (sec_chan_offset == -1) ext_str = "Below";
7023 wifi_setRadioExtChannel(radioIndex, ext_str);
7024
7025 wifi_setRadioCenterChannel(radioIndex, center_chan);
7026
7027 char mhz_str[16];
7028 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
7029 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
7030
7031 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7032
7033 return RETURN_OK;
7034}
7035
7036INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
7037{
7038 char cmd[1024] = {0};
7039 char buf[1024] = {0};
7040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7041 wifi_neighbor_ap2_t *scan_array = NULL;
7042 int scan_count=0;
7043 int i =0;
7044 int freq=0;
7045 size_t len=0;
7046 FILE *f = NULL;
7047 ssize_t read = 0;
7048 char *line =NULL;
7049 char radio_ifname[64];
7050 char secondary_chan[64];
7051 int vht_channel_width = 0;
7052
7053 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
7054 return RETURN_ERR;
7055
7056 /* sched_start is not supported on open source ath9k ath10k firmware
7057 * Using active scan as a workaround */
7058 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
7059 if((f = popen(cmd, "r")) == NULL) {
7060 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7061 return RETURN_ERR;
7062 }
7063 read = getline(&line, &len, f);
7064 while (read != -1) {
7065 if(strncmp(line,"BSS",3) == 0) {
7066 i = scan_count;
7067 scan_count++;
7068 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
7069 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
7070 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
7071
7072 read = getline(&line, &len, f);
7073 sscanf(line," freq: %d", &freq);
7074 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
7075
7076 read = getline(&line, &len, f);
7077 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
7078
7079 read = getline(&line, &len, f);
7080 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
7081 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);
7082 read = getline(&line, &len, f);
7083 if(strncmp(line,"BSS",3)==0) {
7084 // No HT and no VHT => 20Mhz
7085 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
7086 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7087 continue;
7088 }
7089 if(strncmp(line," HT operation:",14)!= 0) {
7090 wifi_dbg_printf("HT output parsing error (%s)\n", line);
7091 goto output_error;
7092 }
7093
7094 read = getline(&line, &len, f);
7095 sscanf(line," * secondary channel offset: %s", &secondary_chan);
7096
7097 if(!strcmp(secondary_chan, "no")) {
7098 //20Mhz
7099 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
7100 }
7101
7102 if(!strcmp(secondary_chan, "above")) {
7103 //40Mhz +
7104 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
7105 }
7106
7107 if(!strcmp(secondary_chan, "below")) {
7108 //40Mhz -
7109 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
7110 }
7111
7112
7113 read = getline(&line, &len, f);
7114 if(strncmp(line," VHT operation:",15) !=0) {
7115 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7116 // No VHT
7117 continue;
7118 }
7119 read = getline(&line, &len, f);
7120 sscanf(line," * channel width: %d", &vht_channel_width);
7121 if(vht_channel_width == 1) {
7122 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
7123 } else {
7124 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
7125 }
7126
7127 }
7128 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7129 read = getline(&line, &len, f);
7130 }
7131 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
7132 *output_array_size = scan_count;
7133 *neighbor_ap_array = scan_array;
7134 free(line);
7135 pclose(f);
7136 return RETURN_OK;
7137
7138output_error:
7139 pclose(f);
7140 free(line);
7141 free(scan_array);
7142 return RETURN_ERR;
7143}
7144INT wifi_getApAssociatedDeviceStats(
7145 INT apIndex,
7146 mac_address_t *clientMacAddress,
7147 wifi_associated_dev_stats_t *associated_dev_stats,
7148 u64 *handle)
7149{
7150 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
7151 char interface_name[50] = {0};
7152 char cmd[1024] = {0};
7153 char mac_str[18] = {0};
7154 char *key = NULL;
7155 char *val = NULL;
7156 FILE *f = NULL;
7157 char *line = NULL;
7158 size_t len = 0;
7159 ssize_t read = 0;
7160
7161 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7162 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7163 return RETURN_ERR;
7164 }
7165
7166 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
7167 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
7168 if((f = popen(cmd, "r")) == NULL) {
7169 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7170 return RETURN_ERR;
7171 }
7172
7173 while ((read = getline(&line, &len, f)) != -1) {
7174 key = strtok(line,":");
7175 val = strtok(NULL,":");
7176
7177 if(!strncmp(key,"rx bytes",8))
7178 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
7179 if(!strncmp(key,"tx bytes",8))
7180 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
7181 if(!strncmp(key,"rx packets",10))
7182 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
7183 if(!strncmp(key,"tx packets",10))
7184 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
7185 if(!strncmp(key,"tx retries",10))
7186 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
7187 if(!strncmp(key,"tx failed",9))
7188 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
7189 if(!strncmp(key,"rx drop misc",13))
7190 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
7191 if(!strncmp(key,"rx bitrate",10)) {
7192 val = strtok(val, " ");
7193 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
7194 }
7195 if(!strncmp(key,"tx bitrate",10)) {
7196 val = strtok(val, " ");
7197 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
7198 }
7199 }
7200 free(line);
7201 pclose(f);
7202 return RETURN_OK;
7203}
7204
7205INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
7206{
7207 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
7208
7209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7210 if (NULL == output_string)
7211 return RETURN_ERR;
7212
7213 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
7214 _syscmd(cmd, buf, sizeof(buf));
7215
7216 //size of SSID name restricted to value less than 32 bytes
7217 snprintf(output_string, 32, "%s", buf);
7218 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7219
7220 return RETURN_OK;
7221}
7222
7223INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
7224{
7225 //char cmd[MAX_CMD_SIZE] = {0};
7226 char config_file[MAX_BUF_SIZE] = {0};
7227 char buf[32] = {0};
7228
7229 if (!output_filterMode)
7230 return RETURN_ERR;
7231
7232 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
7233 //_syscmd(cmd, buf, sizeof(buf));
7234 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7235 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08007236 if(strlen(buf) == 0) {
7237 *output_filterMode = 0;
7238 }
7239 else {
7240 int macaddr_acl_mode = strtol(buf, NULL, 10);
7241 if (macaddr_acl_mode == 1) {
7242 *output_filterMode = 1;
7243 } else if (macaddr_acl_mode == 0) {
7244 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
7245 if (strlen(buf) == 0) {
7246 *output_filterMode = 0;
7247 } else {
7248 *output_filterMode = 2;
7249 }
7250 } else {
7251 return RETURN_ERR;
7252 }
7253 }
developer06a01d92022-09-07 16:32:39 +08007254
7255 return RETURN_OK;
7256}
7257
7258INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
7259{
7260 FILE *fp = NULL;
7261 char str[MAX_BUF_SIZE] = {0};
7262 int wificlientindex = 0 ;
7263 int count = 0;
7264 int signalstrength = 0;
7265 int arr[MACADDRESS_SIZE] = {0};
7266 unsigned char mac[MACADDRESS_SIZE] = {0};
7267 UINT wifi_count = 0;
7268 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7269 char pipeCmd[MAX_CMD_SIZE] = {0};
7270
7271 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7272 *output_array_size = 0;
7273 *associated_dev_array = NULL;
7274 char interface_name[50] = {0};
7275
7276 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7277 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7278 return RETURN_ERR;
7279 }
7280
7281 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7282 fp = popen(pipeCmd, "r");
7283 if (fp == NULL)
7284 {
7285 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7286 return RETURN_ERR;
7287 }
7288
7289 /* Read the output a line at a time - output it. */
7290 fgets(str, sizeof(str)-1, fp);
7291 wifi_count = (unsigned int) atoi ( str );
7292 *output_array_size = wifi_count;
7293 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7294 pclose(fp);
7295
7296 if(wifi_count == 0)
7297 {
7298 return RETURN_OK;
7299 }
7300 else
7301 {
7302 wifi_associated_dev2_t* temp = NULL;
7303 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
7304 *associated_dev_array = temp;
7305 if(temp == NULL)
7306 {
7307 printf("Error Statement. Insufficient memory \n");
7308 return RETURN_ERR;
7309 }
7310
7311 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7312 system(pipeCmd);
7313
7314 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7315 if(fp == NULL)
7316 {
7317 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7318 return RETURN_ERR;
7319 }
7320 fclose(fp);
7321
7322 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7323 fp = popen(pipeCmd, "r");
7324 if(fp)
7325 {
7326 for(count =0 ; count < wifi_count; count++)
7327 {
7328 fgets(str, MAX_BUF_SIZE, fp);
7329 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7330 {
7331 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7332 {
7333 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7334
7335 }
7336 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7337 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]);
7338 }
7339 temp[count].cli_AuthenticationState = 1; //TODO
7340 temp[count].cli_Active = 1; //TODO
7341 }
7342 pclose(fp);
7343 }
7344
7345 //Updating RSSI per client
7346 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7347 fp = popen(pipeCmd, "r");
7348 if(fp)
7349 {
7350 pclose(fp);
7351 }
7352 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7353 if(fp)
7354 {
7355 for(count =0 ; count < wifi_count ;count++)
7356 {
7357 fgets(str, MAX_BUF_SIZE, fp);
7358 signalstrength = atoi(str);
7359 temp[count].cli_RSSI = signalstrength;
7360 }
7361 pclose(fp);
7362 }
7363
7364
7365 //LastDataDownlinkRate
7366 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7367 fp = popen(pipeCmd, "r");
7368 if (fp)
7369 {
7370 pclose(fp);
7371 }
7372 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7373 if (fp)
7374 {
7375 for (count = 0; count < wifi_count; count++)
7376 {
7377 fgets(str, MAX_BUF_SIZE, fp);
7378 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7379 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7380 }
7381 pclose(fp);
7382 }
7383
7384 //LastDataUplinkRate
7385 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7386 fp = popen(pipeCmd, "r");
7387 if (fp)
7388 {
7389 pclose(fp);
7390 }
7391 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7392 if (fp)
7393 {
7394 for (count = 0; count < wifi_count; count++)
7395 {
7396 fgets(str, MAX_BUF_SIZE, fp);
7397 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7398 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7399 }
7400 pclose(fp);
7401 }
7402 }
7403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7404 return RETURN_OK;
7405
7406}
7407
7408INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
7409{
7410#if 0
7411 /*char buf[1024] = {0};
7412 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
7413 _syscmd(cmd, buf, sizeof(buf));*/
7414
7415 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
7416 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
7417 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
7418 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
7419
7420 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.
7421 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].
7422 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].
7423 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].
7424 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
7425 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
7426
7427 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
7428 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
7429 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
7430 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.
7431 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.
7432 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.
7433 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.
7434 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.
7435 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.
7436 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.
7437 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
7438#endif
7439
7440 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08007441 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08007442 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08007443 char pipeCmd[128] = {0};
7444 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08007445 wifi_ssidTrafficStats2_t *out = output_struct;
7446
developerce736392022-09-13 15:24:34 +08007447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007448 if (!output_struct)
7449 return RETURN_ERR;
7450
developerce736392022-09-13 15:24:34 +08007451 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
7452 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
7453 GetInterfaceName(interface_name, HConf_file);
7454 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08007455
developer06a01d92022-09-07 16:32:39 +08007456 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08007457 if (fp == NULL) {
7458 fprintf(stderr, "%s: popen failed\n", __func__);
7459 return RETURN_ERR;
7460 }
7461 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08007462
developerce736392022-09-13 15:24:34 +08007463 if (strlen(str) == 0) // interface not exist
7464 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007465
developerce736392022-09-13 15:24:34 +08007466 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
7467 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08007468 pclose(fp);
7469
developerce736392022-09-13 15:24:34 +08007470 memset(str, 0, sizeof(str));
7471 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08007472 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08007473 if (fp == NULL) {
7474 fprintf(stderr, "%s: popen failed\n", __func__);
7475 return RETURN_ERR;
7476 }
7477 fgets(str, sizeof(str), fp);
7478
7479 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
7480 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08007481 pclose(fp);
developerce736392022-09-13 15:24:34 +08007482
7483 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
7484 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
7485
7486 // Not supported
7487 output_struct->ssid_RetransCount = 0;
7488 output_struct->ssid_FailedRetransCount = 0;
7489 output_struct->ssid_RetryCount = 0;
7490 output_struct->ssid_MultipleRetryCount = 0;
7491 output_struct->ssid_ACKFailureCount = 0;
7492 output_struct->ssid_AggregatedPacketCount = 0;
7493
developer06a01d92022-09-07 16:32:39 +08007494 return RETURN_OK;
7495}
7496
7497//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).
7498INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
7499{
7500 char output_val[16]={'\0'};
7501 char config_file[MAX_BUF_SIZE] = {0};
7502
7503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7504 if (!output)
7505 return RETURN_ERR;
7506 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7507 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
7508
7509 if( strcmp(output_val,"1") == 0 )
7510 *output = TRUE;
7511 else
7512 *output = FALSE;
7513 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7514
7515 return RETURN_OK;
7516}
7517
7518INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
7519{
7520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7521 char str[MAX_BUF_SIZE]={'\0'};
7522 char string[MAX_BUF_SIZE]={'\0'};
7523 char cmd[MAX_CMD_SIZE]={'\0'};
7524 char *ch;
7525 char config_file[MAX_BUF_SIZE] = {0};
7526 struct params params;
7527
7528 if(enable == TRUE)
7529 strcpy(string,"1");
7530 else
7531 strcpy(string,"0");
7532
7533 params.name = "ap_isolate";
7534 params.value = string;
7535
7536 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7537 wifi_hostapdWrite(config_file,&params,1);
7538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7539
7540 return RETURN_OK;
7541}
7542
7543INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
7544{
7545 if (NULL == output_dBm)
7546 return RETURN_ERR;
7547
7548 *output_dBm = 0;
7549 return RETURN_OK;
7550}
7551
7552INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
7553{
7554 return RETURN_OK;
7555}
7556INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
7557{
7558 return RETURN_OK;
7559}
7560INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
7561{
7562 return RETURN_OK;
7563}
7564INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
7565{
7566 return RETURN_OK;
7567}
7568INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
7569{
7570 return RETURN_OK;
7571}
7572INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
7573{
7574 char config_file[MAX_BUF_SIZE] = {0};
7575 struct params list;
7576
7577 list.name = "bss_transition";
7578 list.value = activate?"1":"0";
7579 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
7580 wifi_hostapdWrite(config_file, &list, 1);
7581
7582 return RETURN_OK;
7583}
7584wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
7585
7586void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
7587{
7588 return;
7589}
7590
7591INT wifi_setApCsaDeauth(INT apIndex, INT mode)
7592{
7593 // TODO Implement me!
7594 return RETURN_OK;
7595}
7596
7597INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
7598{
7599 // TODO Implement me!
7600 return RETURN_OK;
7601}
7602
7603INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
7604{
7605 // TODO Implement me!
7606 //Apply wifi_pushRadioChannel() instantly
7607 return RETURN_ERR;
7608}
7609
7610INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
7611{
7612 // TODO Implement me!
7613 return RETURN_OK;
7614}
7615
7616#ifdef HAL_NETLINK_IMPL
7617static int tidStats_callback(struct nl_msg *msg, void *arg) {
7618 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7619 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7620 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
7621 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
7622 int rem , tid_index = 0;
7623
7624 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
7625 wifi_associated_dev_tid_entry_t *stats_entry;
7626
7627 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
7628 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
7629 };
7630 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
7631 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
7632 };
7633
7634 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7635 genlmsg_attrlen(gnlh, 0), NULL);
7636
7637
7638 if (!tb[NL80211_ATTR_STA_INFO]) {
7639 fprintf(stderr, "station stats missing!\n");
7640 return NL_SKIP;
7641 }
7642
7643 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
7644 tb[NL80211_ATTR_STA_INFO],
7645 stats_policy)) {
7646 fprintf(stderr, "failed to parse nested attributes!\n");
7647 return NL_SKIP;
7648 }
7649
7650 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
7651 {
7652 stats_entry = &out->tid_array[tid_index];
7653
7654 stats_entry->tid = tid_index;
7655 stats_entry->ac = _tid_ac_index_get[tid_index];
7656
7657 if(sinfo[NL80211_STA_INFO_TID_STATS])
7658 {
7659 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
7660 printf("failed to parse nested stats attributes!");
7661 return NL_SKIP;
7662 }
7663 }
7664 if(stats_info[NL80211_TID_STATS_TX_MSDU])
7665 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
7666
7667 if(tid_index < (PS_MAX_TID - 1))
7668 tid_index++;
7669 }
7670 //ToDo: sum_time_ms, ewma_time_ms
7671 return NL_SKIP;
7672}
7673#endif
7674
7675INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
7676{
7677#ifdef HAL_NETLINK_IMPL
7678 Netlink nl;
7679 char if_name[10];
7680
7681 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7682
7683 nl.id = initSock80211(&nl);
7684
7685 if (nl.id < 0) {
7686 fprintf(stderr, "Error initializing netlink \n");
7687 return -1;
7688 }
7689
7690 struct nl_msg* msg = nlmsg_alloc();
7691
7692 if (!msg) {
7693 fprintf(stderr, "Failed to allocate netlink message.\n");
7694 nlfree(&nl);
7695 return -2;
7696 }
7697
7698 genlmsg_put(msg,
7699 NL_AUTO_PORT,
7700 NL_AUTO_SEQ,
7701 nl.id,
7702 0,
7703 0,
7704 NL80211_CMD_GET_STATION,
7705 0);
7706
7707 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
7708 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
7709 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
7710 nl_send_auto(nl.socket, msg);
7711 nl_recvmsgs(nl.socket, nl.cb);
7712 nlmsg_free(msg);
7713 nlfree(&nl);
7714 return RETURN_OK;
7715#else
7716//iw implementation
7717#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
7718#define TOTAL_MAX_LINES 50
7719
7720 char buf[256] = {'\0'}; /* or other suitable maximum line size */
7721 char if_name[10];
7722 FILE *fp=NULL;
7723 char pipeCmd[1024]= {'\0'};
7724 int lines,tid_index=0;
7725 char mac_addr[20] = {'\0'};
7726
7727 wifi_associated_dev_tid_entry_t *stats_entry;
7728
7729 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7730 strcpy(mac_addr,clientMacAddress);
7731
7732 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
7733 fp= popen(pipeCmd,"r");
7734 if(fp == NULL)
7735 {
7736 perror("popen for station dump failed\n");
7737 return RETURN_ERR;
7738 }
7739 pclose(fp);
7740
7741 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
7742 fp=popen(pipeCmd,"r");
7743 if(fp == NULL)
7744 {
7745 perror("popen for grep station failed\n");
7746 return RETURN_ERR;
7747 }
7748 else if(fgets(buf,sizeof(buf),fp) != NULL)
7749 lines=atoi(buf);
7750 else
7751 {
7752 pclose(fp);
7753 fprintf(stderr,"No devices are connected \n");
7754 return RETURN_ERR;
7755 }
7756 pclose(fp);
7757
7758 if(lines == 1)
7759 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
7760
7761 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
7762 {
7763 stats_entry = &tid_stats->tid_array[tid_index];
7764 stats_entry->tid = tid_index;
7765
7766 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);
7767
7768 fp=popen(pipeCmd,"r");
7769 if(fp ==NULL)
7770 {
7771 perror("Failed to read from tid file \n");
7772 return RETURN_ERR;
7773 }
7774 else if(fgets(buf,sizeof(buf),fp) != NULL)
7775 stats_entry->num_msdus = atol(buf);
7776
7777 pclose(fp);
7778 stats_entry->ac = _tid_ac_index_get[tid_index];
7779// TODO:
7780// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
7781// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
7782 }
7783 return RETURN_OK;
7784#endif
7785}
7786
7787
7788INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
7789{
7790 // TODO Implement me!
7791 return RETURN_OK;
7792}
7793
7794
7795INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
7796{
7797 // TODO Implement me!
7798 return RETURN_ERR;
7799}
7800
7801INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
7802{
7803 // TODO Implement me!
7804 return RETURN_ERR;
7805}
7806
7807INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
7808{
7809 // TODO Implement me!
7810 return RETURN_ERR;
7811}
7812
7813INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
7814{
7815 // TODO Implement me!
7816 return RETURN_ERR;
7817}
7818
7819INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
7820{
7821 // TODO Implement me!
7822 return RETURN_ERR;
7823}
7824
7825INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
7826{
7827 // TODO Implement me!
7828 return RETURN_ERR;
7829}
7830
7831INT wifi_steering_eventUnregister(void)
7832{
7833 // TODO Implement me!
7834 return RETURN_ERR;
7835}
7836
7837INT wifi_delApAclDevices(INT apIndex)
7838{
7839#if 0
7840 char cmd[MAX_BUF_SIZE] = {0};
7841 char buf[MAX_BUF_SIZE] = {0};
7842
7843 /* Not reset proof solution */
7844 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
7845 if(_syscmd(cmd,buf,sizeof(buf)))
7846 return RETURN_ERR;
7847#endif
developere6aafda2022-09-13 14:59:28 +08007848 char cmd[MAX_CMD_SIZE]={0};
7849 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08007850
developere6aafda2022-09-13 14:59:28 +08007851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7852 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
7853 if(_syscmd(cmd, buf, sizeof(buf)))
7854 return RETURN_ERR;
7855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007856
7857 return RETURN_OK;
7858}
7859
7860#ifdef HAL_NETLINK_IMPL
7861static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
7862 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7863 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7864 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
7865 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
7866 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
7867 char mac_addr[20],dev[20];
7868
7869 nla_parse(tb,
7870 NL80211_ATTR_MAX,
7871 genlmsg_attrdata(gnlh, 0),
7872 genlmsg_attrlen(gnlh, 0),
7873 NULL);
7874
7875 if(!tb[NL80211_ATTR_STA_INFO]) {
7876 fprintf(stderr, "sta stats missing!\n");
7877 return NL_SKIP;
7878 }
7879
7880 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
7881 fprintf(stderr, "failed to parse nested attributes!\n");
7882 return NL_SKIP;
7883 }
7884 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
7885
7886 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
7887
7888 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
7889 fprintf(stderr, "failed to parse nested rate attributes!");
7890 return NL_SKIP;
7891 }
7892
7893 if(sinfo[NL80211_STA_INFO_TID_STATS])
7894 {
7895 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
7896 printf("failed to parse nested stats attributes!");
7897 return NL_SKIP;
7898 }
7899 }
7900
7901 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
7902 {
7903 printf("Type is VHT\n");
7904 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
7905 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
7906
7907 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
7908 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
7909 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
7910 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
7911 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
7912 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
7913 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
7914 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
7915 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
7916 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
7917 }
7918 else
7919 {
7920 printf(" OFDM or CCK \n");
7921 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
7922 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
7923 }
7924
7925 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
7926 if(rinfo[NL80211_RATE_INFO_MCS])
7927 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
7928 }
7929 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
7930 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
7931 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
7932 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
7933
7934 if(stats_info[NL80211_TID_STATS_RX_MSDU])
7935 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
7936
7937 if (sinfo[NL80211_STA_INFO_SIGNAL])
7938 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
7939 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
7940 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
7941 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
7942 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
7943 //rssi_array need to be filled
7944 return NL_SKIP;
7945}
7946#endif
7947
7948INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
7949{
7950#ifdef HAL_NETLINK_IMPL
7951 Netlink nl;
7952 char if_name[10];
7953
7954 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
7955
7956 if (*output_array_size <= 0)
7957 return RETURN_OK;
7958
7959 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
7960 nl.id = initSock80211(&nl);
7961
7962 if (nl.id < 0) {
7963 fprintf(stderr, "Error initializing netlink \n");
7964 return 0;
7965 }
7966
7967 struct nl_msg* msg = nlmsg_alloc();
7968
7969 if (!msg) {
7970 fprintf(stderr, "Failed to allocate netlink message.\n");
7971 nlfree(&nl);
7972 return 0;
7973 }
7974
7975 genlmsg_put(msg,
7976 NL_AUTO_PORT,
7977 NL_AUTO_SEQ,
7978 nl.id,
7979 0,
7980 0,
7981 NL80211_CMD_GET_STATION,
7982 0);
7983
7984 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
7985 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
7986 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
7987 nl_send_auto(nl.socket, msg);
7988 nl_recvmsgs(nl.socket, nl.cb);
7989 nlmsg_free(msg);
7990 nlfree(&nl);
7991 return RETURN_OK;
7992#else
7993 //TODO Implement me
7994 return RETURN_OK;
7995#endif
7996}
7997
7998#ifdef HAL_NETLINK_IMPL
7999static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
8000 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8001 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8002 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8003 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8004 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8005 char mac_addr[20],dev[20];
8006
8007 nla_parse(tb,
8008 NL80211_ATTR_MAX,
8009 genlmsg_attrdata(gnlh, 0),
8010 genlmsg_attrlen(gnlh, 0),
8011 NULL);
8012
8013 if(!tb[NL80211_ATTR_STA_INFO]) {
8014 fprintf(stderr, "sta stats missing!\n");
8015 return NL_SKIP;
8016 }
8017
8018 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8019 fprintf(stderr, "failed to parse nested attributes!\n");
8020 return NL_SKIP;
8021 }
8022
8023 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8024
8025 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8026
8027 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
8028 fprintf(stderr, "failed to parse nested rate attributes!");
8029 return NL_SKIP;
8030 }
8031
8032 if(sinfo[NL80211_STA_INFO_TID_STATS])
8033 {
8034 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8035 printf("failed to parse nested stats attributes!");
8036 return NL_SKIP;
8037 }
8038 }
8039 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
8040 {
8041 printf("Type is VHT\n");
8042 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8043 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8044
8045 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8046 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
8047 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8048 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8049 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8050 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8051 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8052 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8053 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
8054 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8055 }
8056 else
8057 {
8058 printf(" OFDM or CCK \n");
8059 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8060 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
8061 }
8062
8063 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
8064 if(rinfo[NL80211_RATE_INFO_MCS])
8065 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8066 }
8067
8068 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
8069 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
8070 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
8071 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
8072
8073 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
8074 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
8075 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
8076
8077 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8078 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8079
8080 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
8081 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
8082
8083 if(sinfo[NL80211_STA_INFO_TX_FAILED])
8084 ((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]);
8085
8086 return NL_SKIP;
8087}
8088#endif
8089
8090INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8091{
8092#ifdef HAL_NETLINK_IMPL
8093 Netlink nl;
8094 char if_name[10];
8095
8096 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
8097
8098 if (*output_array_size <= 0)
8099 return RETURN_OK;
8100
8101 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8102
8103 nl.id = initSock80211(&nl);
8104
8105 if(nl.id < 0) {
8106 fprintf(stderr, "Error initializing netlink \n");
8107 return 0;
8108 }
8109
8110 struct nl_msg* msg = nlmsg_alloc();
8111
8112 if(!msg) {
8113 fprintf(stderr, "Failed to allocate netlink message.\n");
8114 nlfree(&nl);
8115 return 0;
8116 }
8117
8118 genlmsg_put(msg,
8119 NL_AUTO_PORT,
8120 NL_AUTO_SEQ,
8121 nl.id,
8122 0,
8123 0,
8124 NL80211_CMD_GET_STATION,
8125 0);
8126
8127 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8128 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8129 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
8130 nl_send_auto(nl.socket, msg);
8131 nl_recvmsgs(nl.socket, nl.cb);
8132 nlmsg_free(msg);
8133 nlfree(&nl);
8134 return RETURN_OK;
8135#else
8136 //TODO Implement me
8137 return RETURN_OK;
8138#endif
8139}
8140
8141INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
8142{
8143 // TODO Implement me!
8144 char buf[MAX_BUF_SIZE] = {0};
8145 char config_file[MAX_BUF_SIZE] = {0};
8146
8147 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8148 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
8149 *activate = (strncmp("1",buf,1) == 0);
8150
8151 return RETURN_OK;
8152}
8153
8154INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
8155{
8156 char config_file[MAX_BUF_SIZE] = {0};
8157 struct params list;
8158
8159 list.name = "rrm_neighbor_report";
8160 list.value = activate?"1":"0";
8161 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8162 wifi_hostapdWrite(config_file, &list, 1);
8163
8164 return RETURN_OK;
8165}
8166
8167INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
8168{
8169 char buf[32] = {0};
8170 char config_file[MAX_BUF_SIZE] = {0};
8171
8172 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8173 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
8174 *activate = (strncmp("1",buf,1) == 0);
8175
8176 return RETURN_OK;
8177}
8178#undef HAL_NETLINK_IMPL
8179#ifdef HAL_NETLINK_IMPL
8180static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
8181 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8182 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8183 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
8184 char dev[20];
8185 int freq =0 ;
8186 static int i=0;
8187
8188 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
8189
8190 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
8191 };
8192
8193 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
8194
8195 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8196
8197 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
8198 fprintf(stderr, "survey data missing!\n");
8199 return NL_SKIP;
8200 }
8201
8202 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
8203 {
8204 fprintf(stderr, "failed to parse nested attributes!\n");
8205 return NL_SKIP;
8206 }
8207
8208
8209 if(out[0].array_size == 1 )
8210 {
8211 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
8212 {
8213 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
8214 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
8215 out[0].ch_number = ieee80211_frequency_to_channel(freq);
8216
8217 if (sinfo[NL80211_SURVEY_INFO_NOISE])
8218 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
8219 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
8220 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
8221 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
8222 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
8223 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
8224 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
8225 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
8226 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
8227 if (sinfo[NL80211_SURVEY_INFO_TIME])
8228 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
8229 return NL_STOP;
8230 }
8231 }
8232 else
8233 {
8234 if ( i <= out[0].array_size )
8235 {
8236 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
8237 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
8238 out[i].ch_number = ieee80211_frequency_to_channel(freq);
8239
8240 if (sinfo[NL80211_SURVEY_INFO_NOISE])
8241 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
8242 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
8243 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
8244 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
8245 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
8246 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
8247 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
8248 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
8249 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
8250 if (sinfo[NL80211_SURVEY_INFO_TIME])
8251 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
8252 }
8253 }
8254
8255 i++;
8256 return NL_SKIP;
8257}
8258#endif
8259
8260static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
8261{
8262 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
8263 FILE *fp;
8264
8265 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
8266 {
8267 printf("Creating Frequency-Channel Map\n");
8268 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
8269 }
8270 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
8271 if((fp = popen(command, "r")))
8272 {
8273 fgets(output, sizeof(output), fp);
8274 *freqMHz = atoi(output);
8275 fclose(fp);
8276 }
8277
8278 return 0;
8279}
8280
8281static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
8282{
8283 int freqMHz = -1;
8284 char cmd[MAX_CMD_SIZE] = {'\0'};
8285
8286 ieee80211_channel_to_frequency(channel, &freqMHz);
8287 if (freqMHz == -1) {
8288 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
8289 return -1;
8290 }
8291
8292 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
8293 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
8294 radioIndex, freqMHz);
8295 return -1;
8296 }
8297
8298 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
8299 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
8300 return -1;
8301 }
8302
8303 return 0;
8304}
8305
8306static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
8307{
8308 const char *ptr = buf;
8309 char *key = NULL;
8310 char *val = NULL;
8311 char line[256] = { '\0' };
8312
8313 while (ptr = get_line_from_str_buf(ptr, line)) {
8314 if (strstr(line, "Frequency")) continue;
8315
8316 key = strtok(line, ":");
8317 val = strtok(NULL, " ");
8318 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
8319
8320 if (!strcmp(key, "noise")) {
8321 sscanf(val, "%d", &stats->ch_noise);
8322 if (stats->ch_noise == 0) {
8323 // Workaround for missing noise information.
8324 // Assume -95 for 2.4G and -103 for 5G
8325 if (radioIndex == 0) stats->ch_noise = -95;
8326 if (radioIndex == 1) stats->ch_noise = -103;
8327 }
8328 }
8329 else if (!strcmp(key, "channel active time")) {
8330 sscanf(val, "%llu", &stats->ch_utilization_total);
8331 }
8332 else if (!strcmp(key, "channel busy time")) {
8333 sscanf(val, "%llu", &stats->ch_utilization_busy);
8334 }
8335 else if (!strcmp(key, "channel receive time")) {
8336 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
8337 }
8338 else if (!strcmp(key, "channel transmit time")) {
8339 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
8340 }
8341 };
8342
8343 return 0;
8344}
8345
8346INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
8347{
8348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8349#ifdef HAL_NETLINK_IMPL
8350 Netlink nl;
8351 wifi_channelStats_t_loc local[array_size];
8352 char if_name[10];
8353
8354 local[0].array_size = array_size;
8355
8356 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8357
8358 nl.id = initSock80211(&nl);
8359
8360 if (nl.id < 0) {
8361 fprintf(stderr, "Error initializing netlink \n");
8362 return -1;
8363 }
8364
8365 struct nl_msg* msg = nlmsg_alloc();
8366
8367 if (!msg) {
8368 fprintf(stderr, "Failed to allocate netlink message.\n");
8369 nlfree(&nl);
8370 return -2;
8371 }
8372
8373 genlmsg_put(msg,
8374 NL_AUTO_PORT,
8375 NL_AUTO_SEQ,
8376 nl.id,
8377 0,
8378 NLM_F_DUMP,
8379 NL80211_CMD_GET_SURVEY,
8380 0);
8381
8382 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8383 nl_send_auto(nl.socket, msg);
8384 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
8385 nl_recvmsgs(nl.socket, nl.cb);
8386 nlmsg_free(msg);
8387 nlfree(&nl);
8388 //Copying the Values
8389 for(int i=0;i<array_size;i++)
8390 {
8391 input_output_channelStats_array[i].ch_number = local[i].ch_number;
8392 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
8393 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
8394 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
8395 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
8396 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
8397 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
8398 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
8399 }
8400#else
8401 ULONG channel = 0;
8402 int i;
8403 int number_of_channels = array_size;
8404 char buf[512];
8405 INT ret;
8406 wifi_channelStats_t tmp_stats;
8407
8408 if (number_of_channels == 0) {
8409 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
8410 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
8411 return RETURN_ERR;
8412 }
8413 number_of_channels = 1;
8414 input_output_channelStats_array[0].ch_number = channel;
8415 }
8416
8417 for (i = 0; i < number_of_channels; i++) {
8418
8419 input_output_channelStats_array[i].ch_noise = 0;
8420 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
8421 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
8422 input_output_channelStats_array[i].ch_utilization_busy = 0;
8423 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
8424 input_output_channelStats_array[i].ch_utilization_total = 0;
8425
8426 memset(buf, 0, sizeof(buf));
8427 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
8428 return RETURN_ERR;
8429 }
8430 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
8431 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
8432 return RETURN_ERR;
8433 }
8434
8435 // XXX: fake missing 'self' counter which is not available in iw survey output
8436 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
8437 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
8438
8439 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
8440 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
8441 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
8442 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
8443 input_output_channelStats_array[i].ch_utilization_total *= 1000;
8444
8445 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",
8446 __func__,
8447 input_output_channelStats_array[i].ch_number,
8448 input_output_channelStats_array[i].ch_noise,
8449 input_output_channelStats_array[i].ch_utilization_total,
8450 input_output_channelStats_array[i].ch_utilization_busy,
8451 input_output_channelStats_array[i].ch_utilization_busy_rx,
8452 input_output_channelStats_array[i].ch_utilization_busy_tx,
8453 input_output_channelStats_array[i].ch_utilization_busy_self,
8454 input_output_channelStats_array[i].ch_utilization_busy_ext);
8455 }
8456#endif
8457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8458 return RETURN_OK;
8459}
8460#define HAL_NETLINK_IMPL
8461
8462/* Hostapd events */
8463
8464#ifndef container_of
8465#define offset_of(st, m) ((size_t)&(((st *)0)->m))
8466#define container_of(ptr, type, member) \
8467 ((type *)((char *)ptr - offset_of(type, member)))
8468#endif /* container_of */
8469
8470struct ctrl {
8471 char sockpath[128];
8472 char sockdir[128];
8473 char bss[IFNAMSIZ];
8474 char reply[4096];
8475 int ssid_index;
8476 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
8477 void (*overrun)(struct ctrl *ctrl);
8478 struct wpa_ctrl *wpa;
8479 unsigned int ovfl;
8480 size_t reply_len;
8481 int initialized;
8482 ev_timer retry;
8483 ev_timer watchdog;
8484 ev_stat stat;
8485 ev_io io;
8486};
8487static wifi_newApAssociatedDevice_callback clients_connect_cb;
8488static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
8489static struct ctrl wpa_ctrl[MAX_APS];
8490static int initialized;
8491
8492static unsigned int ctrl_get_drops(struct ctrl *ctrl)
8493{
8494 char cbuf[256] = {};
8495 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
8496 struct cmsghdr *cmsg;
8497 unsigned int ovfl = ctrl->ovfl;
8498 unsigned int drop;
8499
8500 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
8501 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
8502 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
8503 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
8504
8505 drop = ovfl - ctrl->ovfl;
8506 ctrl->ovfl = ovfl;
8507
8508 return drop;
8509}
8510
8511static void ctrl_close(struct ctrl *ctrl)
8512{
8513 if (ctrl->io.cb)
8514 ev_io_stop(EV_DEFAULT_ &ctrl->io);
8515 if (ctrl->retry.cb)
8516 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
8517 if (!ctrl->wpa)
8518 return;
8519
8520 wpa_ctrl_detach(ctrl->wpa);
8521 wpa_ctrl_close(ctrl->wpa);
8522 ctrl->wpa = NULL;
8523 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
8524}
8525
8526static void ctrl_process(struct ctrl *ctrl)
8527{
8528 const char *str;
8529 int drops;
8530 int level;
8531 int err;
8532
8533 /* Example events:
8534 *
8535 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
8536 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
8537 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
8538 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
8539 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
8540 */
8541 if (!(str = index(ctrl->reply, '>')))
8542 return;
8543 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
8544 return;
8545
8546 str++;
8547
8548 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
8549 if (!(str = index(ctrl->reply, ' ')))
8550 return;
8551 wifi_associated_dev_t sta;
8552 memset(&sta, 0, sizeof(sta));
8553
8554 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
8555 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
8556 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
8557
8558 sta.cli_Active=true;
8559
8560 (clients_connect_cb)(ctrl->ssid_index, &sta);
8561 goto handled;
8562 }
8563
8564 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
8565 if (!(str = index(ctrl->reply, ' ')))
8566 return;
8567
8568 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
8569 goto handled;
8570 }
8571
8572 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
8573 printf("CTRL_WPA: handle TERMINATING event\n");
8574 goto retry;
8575 }
8576
8577 if (strncmp("AP-DISABLED", str, 11) == 0) {
8578 printf("CTRL_WPA: handle AP-DISABLED\n");
8579 goto retry;
8580 }
8581
8582 printf("Event not supported!!\n");
8583
8584handled:
8585
8586 if ((drops = ctrl_get_drops(ctrl))) {
8587 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
8588 if (ctrl->overrun)
8589 ctrl->overrun(ctrl);
8590 }
8591
8592 return;
8593
8594retry:
8595 printf("WPA_CTRL: closing\n");
8596 ctrl_close(ctrl);
8597 printf("WPA_CTRL: retrying from ctrl prcoess\n");
8598 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
8599}
8600
8601static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
8602{
8603 struct ctrl *ctrl = container_of(io, struct ctrl, io);
8604 int err;
8605
8606 memset(ctrl->reply, 0, sizeof(ctrl->reply));
8607 ctrl->reply_len = sizeof(ctrl->reply) - 1;
8608 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
8609 ctrl->reply[ctrl->reply_len] = 0;
8610 if (err < 0) {
8611 if (errno == EAGAIN || errno == EWOULDBLOCK)
8612 return;
8613 ctrl_close(ctrl);
8614 ev_timer_again(EV_A_ &ctrl->retry);
8615 return;
8616 }
8617
8618 ctrl_process(ctrl);
8619}
8620
8621static int ctrl_open(struct ctrl *ctrl)
8622{
8623 int fd;
8624
8625 if (ctrl->wpa)
8626 return 0;
8627
8628 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
8629 if (!ctrl->wpa)
8630 goto err;
8631
8632 if (wpa_ctrl_attach(ctrl->wpa) < 0)
8633 goto err_close;
8634
8635 fd = wpa_ctrl_get_fd(ctrl->wpa);
8636 if (fd < 0)
8637 goto err_detach;
8638
8639 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
8640 goto err_detach;
8641
8642 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
8643 ev_io_start(EV_DEFAULT_ &ctrl->io);
8644
8645 return 0;
8646
8647err_detach:
8648 wpa_ctrl_detach(ctrl->wpa);
8649err_close:
8650 wpa_ctrl_close(ctrl->wpa);
8651err:
8652 ctrl->wpa = NULL;
8653 return -1;
8654}
8655
8656static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
8657{
8658 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
8659
8660 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
8661 ctrl_open(ctrl);
8662}
8663
8664static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
8665{
8666 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
8667
8668 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
8669 if (ctrl_open(ctrl) == 0) {
8670 printf("WPA_CTRL: retry successful\n");
8671 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
8672 }
8673}
8674
8675int ctrl_enable(struct ctrl *ctrl)
8676{
8677 if (ctrl->wpa)
8678 return 0;
8679
8680 if (!ctrl->stat.cb) {
8681 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
8682 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
8683 }
8684
8685 if (!ctrl->retry.cb) {
8686 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
8687 }
8688
8689 return ctrl_open(ctrl);
8690}
8691
8692static void
8693ctrl_msg_cb(char *buf, size_t len)
8694{
8695 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
8696
8697 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
8698 ctrl_process(ctrl);
8699}
8700
8701static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
8702{
8703 int err;
8704
8705 if (!ctrl->wpa)
8706 return -1;
8707 if (*reply_len < 2)
8708 return -1;
8709
8710 (*reply_len)--;
8711 ctrl->reply_len = sizeof(ctrl->reply);
8712 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
8713 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
8714 if (err < 0)
8715 return err;
8716
8717 if (ctrl->reply_len > *reply_len)
8718 ctrl->reply_len = *reply_len;
8719
8720 *reply_len = ctrl->reply_len;
8721 memcpy(reply, ctrl->reply, *reply_len);
8722 reply[*reply_len - 1] = 0;
8723 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
8724 return 0;
8725}
8726
8727static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
8728{
8729 const char *pong = "PONG";
8730 const char *ping = "PING";
8731 char reply[1024];
8732 size_t len = sizeof(reply);
8733 int err;
8734 ULONG s, snum;
8735 INT ret;
8736 BOOL status;
8737
8738 printf("WPA_CTRL: watchdog cb\n");
8739
8740 ret = wifi_getSSIDNumberOfEntries(&snum);
8741 if (ret != RETURN_OK) {
8742 printf("%s: failed to get SSID count", __func__);
8743 return;
8744 }
8745
8746 if (snum > MAX_APS) {
8747 printf("more ssid than supported! %lu\n", snum);
8748 return;
8749 }
8750
8751 for (s = 0; s < snum; s++) {
8752 if (wifi_getApEnable(s, &status) != RETURN_OK) {
8753 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
8754 continue;
8755 }
8756 if (status == false) continue;
8757
8758 memset(reply, 0, sizeof(reply));
8759 len = sizeof(reply);
8760 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
8761 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
8762 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
8763 continue;
8764
8765 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
8766 ctrl_close(&wpa_ctrl[s]);
8767 printf("WPA_CTRL: ev_timer_again %d\n", s);
8768 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
8769 }
8770}
8771
8772static int init_wpa()
8773{
8774 int ret = 0, i = 0;
8775 ULONG s, snum;
8776
8777 ret = wifi_getSSIDNumberOfEntries(&snum);
8778 if (ret != RETURN_OK) {
8779 printf("%s: failed to get SSID count", __func__);
8780 return RETURN_ERR;
8781 }
8782
8783 if (snum > MAX_APS) {
8784 printf("more ssid than supported! %lu\n", snum);
8785 return RETURN_ERR;
8786 }
8787
8788 for (s = 0; s < snum; s++) {
8789 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
8790 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
8791 wpa_ctrl[s].ssid_index = s;
8792 ctrl_enable(&wpa_ctrl[s]);
8793 }
8794
8795 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
8796 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
8797
8798 initialized = 1;
8799 printf("WPA_CTRL: initialized\n");
8800
8801 return RETURN_OK;
8802}
8803
8804void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
8805{
8806 clients_connect_cb = callback_proc;
8807 if (!initialized)
8808 init_wpa();
8809}
8810
8811void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
8812{
8813 clients_disconnect_cb = callback_proc;
8814 if (!initialized)
8815 init_wpa();
8816}
8817
8818INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
8819{
8820 // TODO Implement me!
8821 return RETURN_ERR;
8822}
8823
8824INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
8825{
8826 // TODO Implement me!
8827 return RETURN_ERR;
8828}
8829
8830INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
8831{
8832 int i;
8833 char cmd[256];
8834 char channel_numbers_buf[256];
8835 char dfs_state_buf[256];
8836 char line[256];
8837 const char *ptr;
8838
8839 memset(cmd, 0, sizeof(cmd));
8840 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
8841 memset(line, 0, sizeof(line));
8842 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
8843 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
8844
8845 if (radioIndex == 0) { // 2.4G - all allowed
8846 if (outputMapSize < 11) {
8847 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
8848 return RETURN_ERR;
8849 }
8850
8851 for (i = 0; i < 11; i++) {
8852 outputMap[i].ch_number = i + 1;
8853 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
8854 }
8855
8856 return RETURN_OK;
8857 }
8858
8859 if (radioIndex == 1) { // 5G
8860// Example output of iw list:
8861//
8862// Frequencies:
8863// * 5180 MHz [36] (17.0 dBm)
8864// * 5200 MHz [40] (17.0 dBm)
8865// * 5220 MHz [44] (17.0 dBm)
8866// * 5240 MHz [48] (17.0 dBm)
8867// * 5260 MHz [52] (23.0 dBm) (radar detection)
8868// DFS state: usable (for 78930 sec)
8869// DFS CAC time: 60000 ms
8870// * 5280 MHz [56] (23.0 dBm) (radar detection)
8871// DFS state: usable (for 78930 sec)
8872// DFS CAC time: 60000 ms
8873// * 5300 MHz [60] (23.0 dBm) (radar detection)
8874// DFS state: usable (for 78930 sec)
8875// DFS CAC time: 60000 ms
8876// * 5320 MHz [64] (23.0 dBm) (radar detection)
8877// DFS state: usable (for 78930 sec)
8878// DFS CAC time: 60000 ms
8879// * 5500 MHz [100] (disabled)
8880// * 5520 MHz [104] (disabled)
8881// * 5540 MHz [108] (disabled)
8882// * 5560 MHz [112] (disabled)
8883//
8884// Below command should fetch channel numbers of each enabled channel in 5GHz band:
8885 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
8886 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
8887 return RETURN_ERR;
8888 }
8889
8890 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
8891 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
8892 return RETURN_ERR;
8893 }
8894
8895 ptr = channel_numbers_buf;
8896 i = 0;
8897 while (ptr = get_line_from_str_buf(ptr, line)) {
8898 if (i >= outputMapSize) {
8899 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
8900 return RETURN_ERR;
8901 }
8902 sscanf(line, "%d", &outputMap[i].ch_number);
8903
8904 memset(cmd, 0, sizeof(cmd));
8905 // Below command should fetch string for DFS state (usable, available or unavailable)
8906 // Example line: "DFS state: usable (for 78930 sec)"
8907 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) {
8908 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
8909 return RETURN_ERR;
8910 }
8911
8912 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
8913 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
8914 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
8915 return RETURN_ERR;
8916 }
8917
8918 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
8919
8920 if (!strcmp(dfs_state_buf, "usable")) {
8921 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
8922 } else if (!strcmp(dfs_state_buf, "available")) {
8923 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
8924 } else if (!strcmp(dfs_state_buf, "unavailable")) {
8925 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
8926 } else {
8927 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
8928 }
8929 i++;
8930 }
8931
8932 return RETURN_OK;
8933 }
8934
8935 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
8936 return RETURN_ERR;
8937}
8938
8939INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
8940{
8941 // TODO Implement me!
8942 return RETURN_ERR;
8943}
8944
8945INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
8946{
8947 return RETURN_OK;
8948}
8949
8950INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
8951{
8952 // TODO Implement me!
8953 return RETURN_ERR;
8954}
8955
8956INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
8957{
8958 // TODO API refrence Implementaion is present on RPI hal
8959 return RETURN_ERR;
8960}
8961
8962INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
8963{
8964 //TO-Do Implement this
8965 txpwr_pcntg = 0;
8966 return RETURN_OK;
8967}
8968
8969INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
8970{
8971 //Zero-wait DFS not supported
8972 return RETURN_ERR;
8973}
8974
8975INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
8976{
8977 //Zero-wait DFS not supported
8978 return RETURN_ERR;
8979}
8980
8981INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
8982{
8983 *supported = false;
8984 return RETURN_OK;
8985}
8986
8987/* multi-psk support */
8988INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
8989{
8990 char cmd[256];
8991
8992 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
8993 AP_PREFIX,
8994 apIndex,
8995 mac[0],
8996 mac[1],
8997 mac[2],
8998 mac[3],
8999 mac[4],
9000 mac[5]
9001 );
9002 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
9003 _syscmd(cmd, key->wifi_keyId, 64);
9004
9005
9006 return RETURN_OK;
9007}
9008
9009INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
9010{
9011 FILE *fd = NULL;
9012 char fname[100];
9013 char cmd[128] = {0};
9014 char out[64] = {0};
9015 wifi_key_multi_psk_t * key = NULL;
9016 if(keysNumber < 0)
9017 return RETURN_ERR;
9018
9019 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
9020 fd = fopen(fname, "w");
9021 if (!fd) {
9022 return RETURN_ERR;
9023 }
9024 key= (wifi_key_multi_psk_t *) keys;
9025 for(int i=0; i<keysNumber; ++i, key++) {
9026 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
9027 }
9028 fclose(fd);
9029
9030 //reload file
9031 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
9032 _syscmd(cmd, out, 64);
9033 return RETURN_OK;
9034}
9035
9036INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
9037{
9038 FILE *fd = NULL;
9039 char fname[100];
9040 char * line = NULL;
9041 char * pos = NULL;
9042 size_t len = 0;
9043 ssize_t read = 0;
9044 INT ret = RETURN_OK;
9045 wifi_key_multi_psk_t *keys_it = NULL;
9046
9047 if (keysNumber < 1) {
9048 return RETURN_ERR;
9049 }
9050
9051 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
9052 fd = fopen(fname, "r");
9053 if (!fd) {
9054 return RETURN_ERR;
9055 }
9056
9057 if (keys == NULL) {
9058 ret = RETURN_ERR;
9059 goto close;
9060 }
9061
9062 keys_it = keys;
9063 while ((read = getline(&line, &len, fd)) != -1) {
9064 //Strip trailing new line if present
9065 if (read > 0 && line[read-1] == '\n') {
9066 line[read-1] = '\0';
9067 }
9068
9069 if(strcmp(line,"keyid=")) {
9070 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
9071 if (!(pos = index(line, ' '))) {
9072 ret = RETURN_ERR;
9073 goto close;
9074 }
9075 pos++;
9076 //Here should be 00:00:00:00:00:00
9077 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
9078 printf("Not supported MAC: %s\n", pos);
9079 }
9080 if (!(pos = index(pos, ' '))) {
9081 ret = RETURN_ERR;
9082 goto close;
9083 }
9084 pos++;
9085
9086 //The rest is PSK
9087 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
9088 keys_it++;
9089
9090 if(--keysNumber <= 0)
9091 break;
9092 }
9093 }
9094
9095close:
9096 free(line);
9097 fclose(fd);
9098 return ret;
9099}
9100/* end of multi-psk support */
9101
9102INT wifi_setNeighborReports(UINT apIndex,
9103 UINT numNeighborReports,
9104 wifi_NeighborReport_t *neighborReports)
9105{
9106 char cmd[256] = { 0 };
9107 char hex_bssid[13] = { 0 };
9108 char bssid[18] = { 0 };
9109 char nr[256] = { 0 };
9110 char ssid[256];
9111 char hex_ssid[256];
9112 INT ret;
9113
9114 /*rmeove all neighbors*/
9115 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
9116 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);
9117 system(cmd);
9118
9119 for(unsigned int i = 0; i < numNeighborReports; i++)
9120 {
9121 memset(ssid, 0, sizeof(ssid));
9122 ret = wifi_getSSIDName(apIndex, ssid);
9123 if (ret != RETURN_OK)
9124 return RETURN_ERR;
9125
9126 memset(hex_ssid, 0, sizeof(hex_ssid));
9127 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
9128 sprintf(hex_ssid + k,"%02x", ssid[j]);
9129
9130 snprintf(hex_bssid, sizeof(hex_bssid),
9131 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
9132 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
9133 snprintf(bssid, sizeof(bssid),
9134 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
9135 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
9136
9137 snprintf(nr, sizeof(nr),
9138 "%s" // bssid
9139 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
9140 "%02hhx" // operclass
9141 "%02hhx" // channel
9142 "%02hhx", // phy_mode
9143 hex_bssid,
9144 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
9145 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
9146 neighborReports[i].opClass,
9147 neighborReports[i].channel,
9148 neighborReports[i].phyTable);
9149
9150 snprintf(cmd, sizeof(cmd),
9151 "hostapd_cli set_neighbor "
9152 "%s " // bssid
9153 "ssid=%s " // ssid
9154 "nr=%s " // nr
9155 "-i %s%d",
9156 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
9157
9158 if (WEXITSTATUS(system(cmd)) != 0)
9159 {
9160 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
9161 }
9162 }
9163
9164 return RETURN_OK;
9165}
9166
9167INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
9168{
9169 return RETURN_OK;
9170}
9171
9172#ifdef _WIFI_HAL_TEST_
9173int main(int argc,char **argv)
9174{
9175 int index;
9176 INT ret=0;
9177 char buf[1024]="";
9178
9179 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9180 if(argc<3)
9181 {
9182 if(argc==2)
9183 {
9184 if(!strcmp(argv[1], "init"))
9185 return wifi_init();
9186 if(!strcmp(argv[1], "reset"))
9187 return wifi_reset();
9188 if(!strcmp(argv[1], "wifi_getHalVersion"))
9189 {
9190 char buffer[64];
9191 if(wifi_getHalVersion(buffer)==RETURN_OK)
9192 printf("Version: %s\n", buffer);
9193 else
9194 printf("Error in wifi_getHalVersion\n");
9195 return RETURN_OK;
9196 }
9197 }
9198 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
9199 exit(-1);
9200 }
9201
9202 index = atoi(argv[2]);
9203 if(strstr(argv[1], "wifi_getApName")!=NULL)
9204 {
9205 wifi_getApName(index,buf);
9206 printf("Ap name is %s \n",buf);
9207 return 0;
9208 }
9209 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
9210 {
9211 BOOL b = FALSE;
9212 BOOL *output_bool = &b;
9213 wifi_getRadioAutoChannelEnable(index,output_bool);
9214 printf("Channel enabled = %d \n",b);
9215 return 0;
9216 }
9217 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
9218 {
9219 wifi_getApWpaEncryptionMode(index,buf);
9220 printf("encryption enabled = %s\n",buf);
9221 return 0;
9222 }
9223 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
9224 {
9225 BOOL b = FALSE;
9226 BOOL *output_bool = &b;
9227 wifi_getApSsidAdvertisementEnable(index,output_bool);
9228 printf("advertisment enabled = %d\n",b);
9229 return 0;
9230 }
9231 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
9232 {
9233 if(argc <= 3 )
9234 {
9235 printf("Insufficient arguments \n");
9236 exit(-1);
9237 }
9238
9239 char sta[20] = {'\0'};
9240 ULLONG handle= 0;
9241 strcpy(sta,argv[3]);
9242 mac_address_t st;
9243 mac_addr_aton(st,sta);
9244
9245 wifi_associated_dev_tid_stats_t tid_stats;
9246 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
9247 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
9248 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);
9249 }
9250
9251 if(strstr(argv[1], "getApEnable")!=NULL) {
9252 BOOL enable;
9253 ret=wifi_getApEnable(index, &enable);
9254 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
9255 }
9256 else if(strstr(argv[1], "setApEnable")!=NULL) {
9257 BOOL enable = atoi(argv[3]);
9258 ret=wifi_setApEnable(index, enable);
9259 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
9260 }
9261 else if(strstr(argv[1], "getApStatus")!=NULL) {
9262 char status[64];
9263 ret=wifi_getApStatus(index, status);
9264 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
9265 }
9266 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
9267 {
9268 wifi_getSSIDNameStatus(index,buf);
9269 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
9270 return 0;
9271 }
9272 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
9273 wifi_ssidTrafficStats2_t stats={0};
9274 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
9275 printf("%s %d: returns %d\n", argv[1], index, ret);
9276 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
9277 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
9278 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
9279 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
9280 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
9281 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
9282 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
9283 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
9284 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
9285 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
9286 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
9287 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
9288 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
9289 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
9290 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
9291 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
9292 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
9293 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
9294 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
9295 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
9296 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
9297 }
9298 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
9299 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
9300 UINT array_size=0;
9301 UINT i=0;
9302 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
9303 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
9304 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
9305 printf(" neighbor %d:\n", i);
9306 printf(" ap_SSID =%s\n", pt->ap_SSID);
9307 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
9308 printf(" ap_Mode =%s\n", pt->ap_Mode);
9309 printf(" ap_Channel =%d\n", pt->ap_Channel);
9310 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
9311 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
9312 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
9313 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
9314 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
9315 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
9316 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
9317 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
9318 printf(" ap_Noise =%d\n", pt->ap_Noise);
9319 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
9320 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
9321 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
9322 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
9323 }
9324 if(neighbor_ap_array)
9325 free(neighbor_ap_array); //make sure to free the list
9326 }
9327 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
9328 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
9329 UINT array_size=0;
9330 UINT i=0;
9331 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
9332 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
9333 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
9334 printf(" associated_dev %d:\n", i);
9335 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
9336 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
9337 printf(" cli_SNR =%d\n", pt->cli_SNR);
9338 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
9339 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
9340 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
9341 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
9342 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
9343 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
9344 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
9345 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
9346 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
9347 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
9348 }
9349 if(associated_dev_array)
9350 free(associated_dev_array); //make sure to free the list
9351 }
9352
9353 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
9354 {
9355#define MAX_ARRAY_SIZE 64
9356 int i, array_size;
9357 char *p, *ch_str;
9358 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
9359
9360 if(argc != 5)
9361 {
9362 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
9363 exit(-1);
9364 }
9365 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
9366
9367 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
9368 {
9369 strtok_r(ch_str, ",", &p);
9370 input_output_channelStats_array[i].ch_number = atoi(ch_str);
9371 }
9372 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
9373 if(!array_size)
9374 array_size=1;//Need to print current channel statistics
9375 for(i=0; i<array_size; i++)
9376 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
9377 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
9378 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
9379 input_output_channelStats_array[i].ch_number,\
9380 input_output_channelStats_array[i].ch_noise,\
9381 input_output_channelStats_array[i].ch_utilization_busy_rx,\
9382 input_output_channelStats_array[i].ch_utilization_busy_tx,\
9383 input_output_channelStats_array[i].ch_utilization_busy,\
9384 input_output_channelStats_array[i].ch_utilization_busy_ext,\
9385 input_output_channelStats_array[i].ch_utilization_total);
9386 }
9387
9388 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
9389 {
9390 if(argc <= 3 )
9391 {
9392 printf("Insufficient arguments \n");
9393 exit(-1);
9394 }
9395 char mac_addr[20] = {'\0'};
9396 wifi_device_t output_struct;
9397 int dev_index = atoi(argv[3]);
9398
9399 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
9400 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
9401 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);
9402 }
9403
9404 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
9405 {
9406 if (argc <= 3)
9407 {
9408 printf("Insufficient arguments\n");
9409 exit(-1);
9410 }
9411 char args[256];
9412 wifi_NeighborReport_t *neighborReports;
9413
9414 neighborReports = calloc(argc - 2, sizeof(neighborReports));
9415 if (!neighborReports)
9416 {
9417 printf("Failed to allocate memory");
9418 exit(-1);
9419 }
9420
9421 for (int i = 3; i < argc; ++i)
9422 {
9423 char *val;
9424 int j = 0;
9425 memset(args, 0, sizeof(args));
9426 strncpy(args, argv[i], sizeof(args));
9427 val = strtok(args, ";");
9428 while (val != NULL)
9429 {
9430 if (j == 0)
9431 {
9432 mac_addr_aton(neighborReports[i - 3].bssid, val);
9433 } else if (j == 1)
9434 {
9435 neighborReports[i - 3].info = strtol(val, NULL, 16);
9436 } else if (j == 2)
9437 {
9438 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
9439 } else if (j == 3)
9440 {
9441 neighborReports[i - 3].channel = strtol(val, NULL, 16);
9442 } else if (j == 4)
9443 {
9444 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
9445 } else {
9446 printf("Insufficient arguments]n\n");
9447 exit(-1);
9448 }
9449 val = strtok(NULL, ";");
9450 j++;
9451 }
9452 }
9453
9454 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
9455 if (ret != RETURN_OK)
9456 {
9457 printf("wifi_setNeighborReports ret = %d", ret);
9458 exit(-1);
9459 }
9460 }
9461 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
9462 {
9463 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
9464 printf("%s.\n", buf);
9465 else
9466 printf("Error returned\n");
9467 }
9468 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
9469 {
9470 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
9471 printf("%s.\n", buf);
9472 else
9473 printf("Error returned\n");
9474 }
9475 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
9476 {
9477 if (argc <= 2)
9478 {
9479 printf("Insufficient arguments\n");
9480 exit(-1);
9481 }
9482 char buf[64]= {'\0'};
9483 wifi_getRadioOperatingChannelBandwidth(index,buf);
9484 printf("Current bandwidth is %s \n",buf);
9485 return 0;
9486 }
9487 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
9488 {
9489 if (argc <= 5)
9490 {
9491 printf("Insufficient arguments\n");
9492 exit(-1);
9493 }
9494 UINT channel = atoi(argv[3]);
9495 UINT width = atoi(argv[4]);
9496 UINT beacon = atoi(argv[5]);
9497 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
9498 printf("Result = %d", ret);
9499 }
9500
9501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9502 return 0;
9503}
9504
9505#endif
9506
9507#ifdef WIFI_HAL_VERSION_3
9508
9509INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
9510{
9511 // The only par-radio parameter is a channel number, however there's a 'dynamic' API
9512 // to change it ("wifi_pushRadioChannel2()") that is used instead.
9513 return RETURN_OK;
9514}
9515
9516INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
9517{
9518 INT ret;
9519 char band[128];
9520 ULONG channel;
9521 BOOL enabled;
9522 char buf[256];
9523
9524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9525 printf("Entering %s index = %d\n", __func__, (int)index);
9526
9527 ret = wifi_getRadioEnable(index, &enabled);
9528 if (ret != RETURN_OK)
9529 {
9530 printf("%s: cannot get enabled state for radio index %d\n", __func__,
9531 index);
9532 return RETURN_ERR;
9533 }
9534 operationParam->enable = enabled;
9535
9536 memset(band, 0, sizeof(band));
9537 ret = wifi_getRadioOperatingFrequencyBand(index, band);
9538 if (ret != RETURN_OK)
9539 {
9540 printf("%s: cannot get radio band for radio index %d\n", __func__, index);
9541 return RETURN_ERR;
9542 }
9543
9544 if (!strcmp(band, "2.4GHz"))
9545 {
9546 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
9547 operationParam->variant = WIFI_80211_VARIANT_N;
9548 }
9549 else if (!strcmp(band, "5GHz"))
9550 {
9551 operationParam->band = WIFI_FREQUENCY_5_BAND;
9552 operationParam->variant = WIFI_80211_VARIANT_AC;
9553 }
9554 else
9555 {
9556 printf("%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
9557 band);
9558 }
9559
9560 memset(buf, 0, sizeof(buf));
9561 ret = wifi_getRadioOperatingChannelBandwidth(index, buf); // XXX: handle errors
9562 // XXX: only handle 20/40/80 modes for now
9563 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
9564 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
9565 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
9566 else
9567 {
9568 printf("%s: Unknown HT mode: '%s'\n", __func__, buf);
9569 operationParam->channelWidth = 0;
9570 }
9571
9572 ret = wifi_getRadioChannel(index, &channel);
9573 if (ret != RETURN_OK)
9574 {
9575 printf("%s: Failed to get channel number for radio index %d\n", __func__, index);
9576 channel = 0;
9577 }
9578 operationParam->channel = channel;
9579 operationParam->csa_beacon_count = 15; // XXX: hardcoded for now
9580
9581 operationParam->countryCode = wifi_countrycode_US; // XXX: hardcoded for now
9582
9583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9584 return RETURN_OK;
9585}
9586
9587static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
9588{
9589 if (radioIndex != 0 && radioIndex != 1)
9590 {
9591 printf("%s: Wrong radio index (%d)\n", __func__, index);
9592 return -1;
9593 }
9594
9595 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
9596 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
9597
9598 return (arrayIndex * 2) + radioIndex;
9599}
9600
9601INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
9602{
9603 INT ret;
9604 int i;
9605 BOOL enabled = false;
9606 char buf[256];
9607 wifi_secur_list *secur_item;
9608 int vap_index;
9609 INT mode;
9610 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
9611
9612 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9613 printf("Entering %s index = %d\n", __func__, (int)index);
9614
9615 map->vap_array[index].radio_index = index;
9616 for (i = 0; i < 5; i++)
9617 {
9618 vap_index = array_index_to_vap_index(index, i);
9619 if (vap_index < 0)
9620 {
9621 return RETURN_ERR;
9622 }
9623
9624 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
9625
9626 map->vap_array[i].vap_index = vap_index;
9627
9628 memset(buf, 0, sizeof(buf));
9629 wifi_getApName(vap_index, buf); // XXX: error handling
9630 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
9631
9632 ret = wifi_getSSIDEnable(vap_index, &enabled);
9633 if (ret != RETURN_OK)
9634 {
9635 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
9636 return RETURN_ERR;
9637 }
9638 map->vap_array[i].u.bss_info.enabled = enabled;
9639
9640 memset(buf, 0, sizeof(buf));
9641 wifi_getBaseBSSID(vap_index, buf);
9642 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9643 &map->vap_array[i].u.bss_info.bssid[0],
9644 &map->vap_array[i].u.bss_info.bssid[1],
9645 &map->vap_array[i].u.bss_info.bssid[2],
9646 &map->vap_array[i].u.bss_info.bssid[3],
9647 &map->vap_array[i].u.bss_info.bssid[4],
9648 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
9649
9650 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
9651 map->vap_array[i].u.bss_info.showSsid = enabled;
9652
9653 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
9654 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
9655 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
9656
9657 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
9658 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
9659
9660 memset(buf, 0, sizeof(buf));
9661 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
9662 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
9663
9664 wifi_getApSecurityModeEnabled(vap_index, buf);
9665
9666 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
9667 {
9668 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
9669 return RETURN_ERR;
9670 }
9671 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
9672
9673 memset(buf, 0, sizeof(buf));
9674 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
9675 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);
9676
9677 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
9678 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
9679
9680 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
9681 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
9682
9683 wifi_getApIsolationEnable(vap_index, &enabled);
9684 map->vap_array[i].u.bss_info.isolation = enabled;
9685 }
9686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9687 return RETURN_OK;
9688}
9689
9690INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
9691{
9692 unsigned int i;
9693 wifi_vap_info_t *vap_info = NULL;
9694 int acl_mode;
9695 char *sec_str = NULL;
9696
9697 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9698 printf("Entering %s index = %d\n", __func__, (int)index);
9699 for (i = 0; i < map->num_vaps; i++)
9700 {
9701 vap_info = &map->vap_array[i];
9702 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
9703
9704 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
9705 else
9706 {
9707 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
9708 else acl_mode = 1;
9709 }
9710 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
9711 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
9712 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
9713
9714 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
9715 if (sec_str)
9716 {
9717 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
9718 }
9719 else
9720 {
9721 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
9722 }
9723
9724 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
9725 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
9726
9727 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
9728 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
9729
9730 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
9731
9732 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
9733 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
9734 }
9735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9736 return RETURN_OK;
9737}
9738
9739int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
9740{
9741 char *token, *next;
9742 const char s[2] = ",";
9743 int count =0;
9744
9745 /* get the first token */
9746 token = strtok_r(pchannels, s, &next);
9747
9748 /* walk through other tokens */
9749 while( token != NULL && count < MAX_CHANNELS) {
9750 chlistptr->channels_list[count++] = atoi(token);
9751 token = strtok_r(NULL, s, &next);
9752 }
9753
9754 return count;
9755}
9756
9757static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
9758{
9759 INT status;
9760 wifi_channels_list_t *chlistp;
9761 CHAR output_string[64];
9762 CHAR pchannels[128];
9763
9764 if(rcap == NULL)
9765 {
9766 return RETURN_ERR;
9767 }
9768
9769 rcap->numSupportedFreqBand = 1;
9770 if (1 == radioIndex)
9771 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
9772 else
9773 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
9774
9775
9776 chlistp = &(rcap->channel_list[0]);
9777 memset(pchannels, 0, sizeof(pchannels));
9778
9779 /* possible number of radio channels */
9780 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
9781 {
9782 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
9783 }
9784 /* Number of channels and list*/
9785 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
9786
9787 /* autoChannelSupported */
9788 /* always ON with wifi_getRadioAutoChannelSupported */
9789 rcap->autoChannelSupported = TRUE;
9790
9791 /* DCSSupported */
9792 /* always ON with wifi_getRadioDCSSupported */
9793 rcap->DCSSupported = TRUE;
9794
9795 /* zeroDFSSupported - TBD */
9796 rcap->zeroDFSSupported = FALSE;
9797
9798 /* Supported Country List*/
9799 memset(output_string, 0, sizeof(output_string));
9800 status = wifi_getRadioCountryCode(radioIndex, output_string);
9801 if( status != 0 ) {
9802 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
9803 return RETURN_ERR;
9804 } else {
9805 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
9806 }
9807 if(!strcmp(output_string,"US")){
9808 rcap->countrySupported[0] = wifi_countrycode_US;
9809 rcap->countrySupported[1] = wifi_countrycode_CA;
9810 } else if (!strcmp(output_string,"CA")) {
9811 rcap->countrySupported[0] = wifi_countrycode_CA;
9812 rcap->countrySupported[1] = wifi_countrycode_US;
9813 } else {
9814 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
9815 }
9816
9817 rcap->numcountrySupported = 2;
9818
9819 /* csi */
9820 rcap->csi.maxDevices = 8;
9821 rcap->csi.soudingFrameSupported = TRUE;
9822
9823 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
9824
9825 /* channelWidth - all supported bandwidths */
9826 int i=0;
9827 rcap->channelWidth[i] = 0;
9828 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
9829 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
9830 WIFI_CHANNELBANDWIDTH_40MHZ);
9831
9832 }
9833 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
9834 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
9835 WIFI_CHANNELBANDWIDTH_40MHZ |
9836 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
9837 }
9838
9839
9840 /* mode - all supported variants */
9841 // rcap->mode[i] = WIFI_80211_VARIANT_H;
9842 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
9843 rcap->mode[i] = (WIFI_80211_VARIANT_N);
9844 }
9845 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
9846 rcap->mode[i] = ( WIFI_80211_VARIANT_AC );
9847 }
9848 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
9849 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
9850
9851 /* supportedBitRate - all supported bitrates */
9852 rcap->supportedBitRate[i] = 0;
9853 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
9854 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
9855 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
9856 }
9857 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
9858 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
9859 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
9860 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
9861 }
9862
9863
9864 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
9865 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
9866 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
9867 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
9868 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
9869 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
9870 rcap->cipherSupported = 0;
9871 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
9872 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
9873
9874 return RETURN_OK;
9875}
9876
9877INT wifi_getHalCapability(wifi_hal_capability_t *cap)
9878{
9879 INT status, radioIndex;
9880 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
9881 int iter = 0;
9882 unsigned int j;
9883 wifi_interface_name_idex_map_t *iface_info;
9884
9885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9886
9887 memset(cap, 0, sizeof(wifi_hal_capability_t));
9888
9889 /* version */
9890 cap->version.major = WIFI_HAL_MAJOR_VERSION;
9891 cap->version.minor = WIFI_HAL_MINOR_VERSION;
9892
9893 /* number of radios platform property */
9894 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
9895 _syscmd(cmd, output, sizeof(output));
9896 cap->wifi_prop.numRadios = atoi(output);
9897
9898 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
9899 {
9900 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
9901 if (status != 0) {
9902 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
9903 return RETURN_ERR;
9904 }
9905
9906 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
9907 {
9908 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
9909 {
9910 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
9911 return RETURN_ERR;
9912 }
9913 iface_info = &cap->wifi_prop.interface_map[iter];
9914 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
9915 iface_info->rdk_radio_index = radioIndex;
9916 memset(output, 0, sizeof(output));
9917 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
9918 {
9919 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
9920 }
9921 // TODO: bridge name
9922 // TODO: vlan id
9923 // TODO: primary
9924 iface_info->index = array_index_to_vap_index(radioIndex, j);
9925 memset(output, 0, sizeof(output));
9926 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
9927 {
9928 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
9929 }
9930 iter++;
9931 }
9932 }
9933
9934 cap->BandSteeringSupported = FALSE;
9935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9936 return RETURN_OK;
9937}
9938
9939INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
9940{
9941 //TODO
9942 return RETURN_OK;
9943}
9944
9945INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
9946{
9947 //TODO
9948 return RETURN_OK;
9949}
9950
9951#endif /* WIFI_HAL_VERSION_3 */
9952
9953#ifdef WIFI_HAL_VERSION_3_PHASE2
9954INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
9955{
9956 return RETURN_OK;
9957}
9958#else
9959INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
9960{
9961 char cmd[128];
9962 BOOL status = false;
9963
9964 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
9965 return RETURN_ERR;
9966
9967 output_buf[0] = '\0';
9968
9969 wifi_getApEnable(ap_index,&status);
9970 if (!status)
9971 return RETURN_OK;
9972
9973 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
9974 _syscmd(cmd, output_buf, output_buf_size);
9975
9976 return RETURN_OK;
9977}
9978#endif
developer2f513ab2022-09-13 14:26:06 +08009979
9980INT wifi_getProxyArp(INT apIndex, BOOL *enable)
9981{
9982 char output[16]={'\0'};
9983 char config_file[MAX_BUF_SIZE] = {0};
9984
9985 if (!enable)
9986 return RETURN_ERR;
9987
9988 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9989 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
9990
9991 if (strlen(output) == 0)
9992 *enable = FALSE;
9993 else if (strncmp(output, "1", 1) == 0)
9994 *enable = TRUE;
9995 else
9996 *enable = FALSE;
9997
9998 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
9999 return RETURN_OK;
10000}
developer2d9c30f2022-09-13 15:06:14 +080010001
10002INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
10003{
10004 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
10005 return RETURN_ERR;
10006 *output_enable=TRUE;
10007 return RETURN_OK;
10008}