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