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