blob: a29a5b79f03cb16efce471cbc3e520cc5683e665 [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
2474//Get current Transmit Power, eg "75", "100"
2475//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};
2479 char buf[256]={0};
2480 INT apIndex;
2481 //save config and apply instantly
2482
2483 if (NULL == output_ulong)
2484 return RETURN_ERR;
2485
2486 //zqiu:TODO:save config
2487 apIndex = (radioIndex==0) ?0 :1;
2488
2489 snprintf(cmd, sizeof(cmd), "iwlist %s%d txpower | grep Tx-Power | cut -d'=' -f2", AP_PREFIX, apIndex);
2490 _syscmd(cmd, buf, sizeof(buf));
2491 *output_ulong = atol(buf);
2492
2493 return RETURN_OK;
2494}
2495
2496//Set Transmit Power
2497//The transmite power level is in units of full power for this radio.
2498INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2499{
2500 char cmd[128]={0};
2501 char buf[256]={0};
2502 INT apIndex;
2503
2504 snprintf(cmd, sizeof(cmd), "iwconfig %s%d txpower %lu", AP_PREFIX, radioIndex, TransmitPower);
2505 _syscmd(cmd, buf, sizeof(buf));
2506
2507 return RETURN_OK;
2508}
2509
2510//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2511INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2512{
2513 if (NULL == Supported)
2514 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002515 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002516
2517 return RETURN_OK;
2518}
2519
2520//Get 80211h feature enable
2521INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2522{
developer3885fec2022-09-13 15:13:47 +08002523 char buf[64]={'\0'};
2524 char config_file[64] = {'\0'};
2525
2526 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2527 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002528 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002529
2530 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2531 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002532
developer3885fec2022-09-13 15:13:47 +08002533 if (strncmp(buf, "1", 1) == 0)
2534 *enable = TRUE;
2535 else
2536 *enable = FALSE;
2537
2538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002539 return RETURN_OK;
2540}
2541
2542//Set 80211h feature enable
2543INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2544{
developer3885fec2022-09-13 15:13:47 +08002545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2546 struct params params={'\0'};
2547 char config_file[MAX_BUF_SIZE] = {0};
2548
2549 params.name = "ieee80211h";
2550
2551 if (enable) {
2552 params.value = "1";
2553 } else {
2554 params.value = "0";
2555 }
2556
2557 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2558 wifi_hostapdWrite(config_file, &params, 1);
2559
2560 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2562 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002563}
2564
2565//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.
2566INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2567{
2568 if (NULL == output)
2569 return RETURN_ERR;
2570 *output=100;
2571
2572 return RETURN_OK;
2573}
2574
2575//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.
2576INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2577{
2578 if (NULL == output)
2579 return RETURN_ERR;
2580 *output = -99;
2581
2582 return RETURN_OK;
2583}
2584
2585INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2586{
2587 return RETURN_ERR;
2588}
2589
2590
2591//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2592INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2593{
developer5f222492022-09-13 15:21:52 +08002594 char cmd[MAX_BUF_SIZE]={'\0'};
2595 char buf[MAX_CMD_SIZE]={'\0'};
2596
2597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2598 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002599 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002600
2601 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2602 _syscmd(cmd, buf, sizeof(buf));
2603 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08002604
developer5f222492022-09-13 15:21:52 +08002605 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002606 return RETURN_OK;
2607}
2608
2609INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2610{
developer5f222492022-09-13 15:21:52 +08002611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2612 struct params params={'\0'};
2613 char buf[MAX_BUF_SIZE] = {'\0'};
2614 char config_file[MAX_BUF_SIZE] = {'\0'};
2615
2616 params.name = "beacon_int";
2617 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
2618 params.value = buf;
2619
2620 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2621 wifi_hostapdWrite(config_file, &params, 1);
2622
2623 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2624 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2625 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002626}
2627
2628//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.
2629INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2630{
developer06a01d92022-09-07 16:32:39 +08002631 //TODO: need to revisit below implementation
2632 char *temp;
developere9d0abd2022-09-13 15:40:57 +08002633 char temp_output[128] = {0};
2634 char temp_TransmitRates[64] = {0};
2635 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08002636
2637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2638 if (NULL == output)
2639 return RETURN_ERR;
2640 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08002641 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
2642
2643 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
2644 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
2645 } else {
2646 temp = strtok(temp_TransmitRates," ");
2647 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08002648 {
developere9d0abd2022-09-13 15:40:57 +08002649 // Convert 100 kbps to Mbps
2650 temp[strlen(temp)-1]=0;
2651 if((temp[0]=='5') && (temp[1]=='\0'))
2652 {
2653 temp="5.5";
2654 }
2655 strcat(temp_output,temp);
2656 temp = strtok(NULL," ");
2657 if(temp!=NULL)
2658 {
2659 strcat(temp_output,",");
2660 }
developer06a01d92022-09-07 16:32:39 +08002661 }
developere9d0abd2022-09-13 15:40:57 +08002662 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08002663 }
developer06a01d92022-09-07 16:32:39 +08002664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002665 return RETURN_OK;
2666}
2667
2668INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2669{
2670 char *temp;
2671 char temp1[128];
2672 char temp_output[128];
2673 char temp_TransmitRates[128];
2674 char set[128];
2675 char sub_set[128];
2676 int set_count=0,subset_count=0;
2677 int set_index=0,subset_index=0;
2678 char *token;
2679 int flag=0, i=0;
2680 struct params params={'\0'};
2681 char config_file[MAX_BUF_SIZE] = {0};
2682
2683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2684 if(NULL == TransmitRates)
2685 return RETURN_ERR;
2686 strcpy(sub_set,TransmitRates);
2687
2688 //Allow only supported Data transmit rate to be set
2689 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
2690 token = strtok(sub_set,",");
2691 while( token != NULL ) /* split the basic rate to be set, by comma */
2692 {
2693 sub_set[subset_count]=atoi(token);
2694 subset_count++;
2695 token=strtok(NULL,",");
2696 }
2697 token=strtok(set,",");
2698 while(token!=NULL) /* split the supported rate by comma */
2699 {
2700 set[set_count]=atoi(token);
2701 set_count++;
2702 token=strtok(NULL,",");
2703 }
2704 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
2705 {
2706 for(set_index=0;set_index < set_count;set_index++)
2707 {
2708 flag=0;
2709 if(sub_set[subset_index]==set[set_index])
2710 break;
2711 else
2712 flag=1; /* No match found */
2713 }
2714 if(flag==1)
2715 return RETURN_ERR; //If value not found return Error
2716 }
2717 strcpy(temp_TransmitRates,TransmitRates);
2718
2719 for(i=0;i<strlen(temp_TransmitRates);i++)
2720 {
2721 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
2722 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
2723 {
2724 continue;
2725 }
2726 else
2727 {
2728 return RETURN_ERR;
2729 }
2730 }
2731 strcpy(temp_output,"");
2732 temp = strtok(temp_TransmitRates,",");
2733 while(temp!=NULL)
2734 {
2735 strcpy(temp1,temp);
2736 if(radioIndex==1)
2737 {
2738 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
2739 {
2740 return RETURN_ERR;
2741 }
2742 }
2743
2744 if(strcmp(temp,"5.5")==0)
2745 {
2746 strcpy(temp1,"55");
2747 }
2748 else
2749 {
2750 strcat(temp1,"0");
2751 }
2752 strcat(temp_output,temp1);
2753 temp = strtok(NULL,",");
2754 if(temp!=NULL)
2755 {
2756 strcat(temp_output," ");
2757 }
2758 }
2759 strcpy(TransmitRates,temp_output);
2760
2761 params.name= "basic_rates";
2762 params.value =TransmitRates;
2763
2764 wifi_dbg_printf("\n%s:",__func__);
2765 wifi_dbg_printf("\nparams.value=%s\n",params.value);
2766 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
2767 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2768 wifi_hostapdWrite(config_file,&params,1);
2769 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2770 return RETURN_OK;
2771}
2772
2773//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
2774INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
2775{
2776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2777 FILE *fp = NULL;
2778 char path[256] = {0}, output_string[256] = {0};
2779 int count = 0;
2780 char *interface = NULL;
2781
2782 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
2783 if (fp == NULL)
2784 {
2785 printf("Failed to run command in Function %s\n", __FUNCTION__);
2786 return RETURN_ERR;
2787 }
2788 if (fgets(path, sizeof(path) - 1, fp) != NULL)
2789 {
2790 interface = strchr(path, '=');
2791
2792 if (interface != NULL)
2793 {
2794 strcpy(output_string, interface + 1);
2795 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
2796 interface_name[count] = output_string[count];
2797
2798 interface_name[count] = '\0';
2799 }
2800 }
2801 pclose(fp);
2802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2803 return RETURN_OK;
2804}
2805
2806INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
2807{
2808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2809 output_struct->radio_BytesSent = 0;
2810 output_struct->radio_BytesReceived = 0;
2811 output_struct->radio_PacketsSent = 0;
2812 output_struct->radio_PacketsReceived = 0;
2813 output_struct->radio_ErrorsSent = 0;
2814 output_struct->radio_ErrorsReceived = 0;
2815 output_struct->radio_DiscardPacketsSent = 0;
2816 output_struct->radio_DiscardPacketsReceived = 0;
2817 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2818 return RETURN_OK;
2819}
2820
2821
2822INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
2823{
2824 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2825 CHAR buf[MAX_CMD_SIZE] = {0};
2826 CHAR Value[MAX_BUF_SIZE] = {0};
2827 FILE *fp = NULL;
2828
2829 if (ifname == NULL || strlen(ifname) <= 1)
2830 return RETURN_OK;
2831
2832 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
2833 system(buf);
2834
2835 fp = fopen("/tmp/Radio_Stats.txt", "r");
2836 if(fp == NULL)
2837 {
2838 printf("/tmp/Radio_Stats.txt not exists \n");
2839 return RETURN_ERR;
2840 }
2841 fclose(fp);
2842
2843 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
2844 File_Reading(buf, Value);
2845 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
2846
2847 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
2848 File_Reading(buf, Value);
2849 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
2850
2851 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
2852 File_Reading(buf, Value);
2853 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
2854
2855 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
2856 File_Reading(buf, Value);
2857 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
2858
2859 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
2860 File_Reading(buf, Value);
2861 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
2862
2863 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
2864 File_Reading(buf, Value);
2865 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
2866
2867 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
2868 File_Reading(buf, Value);
2869 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
2870
2871 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
2872 File_Reading(buf, Value);
2873 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
2874
2875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2876 return RETURN_OK;
2877}
2878
2879INT GetIfacestatus(CHAR *interface_name, CHAR *status)
2880{
2881 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2882 CHAR buf[MAX_CMD_SIZE] = {0};
2883 FILE *fp = NULL;
2884 INT count = 0;
2885
2886 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
2887 {
2888 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
2889 File_Reading(buf, status);
2890 }
2891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2892 return RETURN_OK;
2893}
2894
2895//Get detail radio traffic static info
2896INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
2897{
2898
2899#if 0
2900 //ifconfig radio_x
2901 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
2902 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
2903 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
2904 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
2905
2906 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
2907 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
2908 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.
2909 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.
2910
2911 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
2912 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].
2913 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
2914 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.
2915 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
2916 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
2917 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
2918 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
2919 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
2920
2921 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
2922 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
2923 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
2924 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.
2925
2926 return RETURN_OK;
2927#endif
2928
2929 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
2930 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
2931 char buf[MAX_BUF_SIZE] = {0};
2932 char cmd[MAX_CMD_SIZE] = {0};
2933 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
2934
2935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2936 if (NULL == output_struct)
2937 return RETURN_ERR;
2938
2939 if (radioIndex == 0) //2.4GHz ?
2940 {
2941
2942 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
2943
2944 GetIfacestatus(private_interface_name, private_interface_status);
2945
2946 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
2947 File_Reading(cmd, buf);
2948
2949 if (buf[0] == '#')
2950 {
2951 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
2952 }
2953 else
2954 {
2955 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
2956 }
2957
2958 GetIfacestatus(public_interface_name, public_interface_status);
2959
2960 if (strcmp(private_interface_status, "1") == 0)
2961 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
2962 else
2963 wifi_halGetIfStatsNull(&private_radioTrafficStats);
2964
2965 if (strcmp(public_interface_status, "1") == 0)
2966 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
2967 else
2968 wifi_halGetIfStatsNull(&public_radioTrafficStats);
2969 }
2970 else if (radioIndex == 1) //5GHz ?
2971 {
2972 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
2973 GetIfacestatus(private_interface_name, private_interface_status);
2974
2975 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
2976 GetIfacestatus(public_interface_name, public_interface_status);
2977
2978 if (strcmp(private_interface_status, "1") == 0)
2979 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
2980 else
2981 wifi_halGetIfStatsNull(&private_radioTrafficStats);
2982
2983 if (strcmp(public_interface_status, "1") == 0)
2984 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
2985 else
2986 wifi_halGetIfStatsNull(&public_radioTrafficStats);
2987 }
2988
2989 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
2990 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
2991 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
2992 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
2993 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
2994 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
2995 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
2996 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
2997
2998 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
2999 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].
3000 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3001 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.
3002 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
3003 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
3004 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
3005 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
3006 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
3007
3008 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
3009 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
3010 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
3011 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.
3012
3013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3014
3015 return RETURN_OK;
3016}
3017
3018//Set radio traffic static Measureing rules
3019INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3020{
3021 //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
3022 // Else, save the MeasuringRate and MeasuringInterval for future usage
3023
3024 return RETURN_OK;
3025}
3026
3027//To start or stop RadioTrafficStats
3028INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3029{
3030 //zqiu: If the RadioTrafficStats process running
3031 // if(enable)
3032 // return RETURN_OK.
3033 // else
3034 // Stop RadioTrafficStats process
3035 // Else
3036 // if(enable)
3037 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3038 // else
3039 // return RETURN_OK.
3040
3041 return RETURN_OK;
3042}
3043
3044//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
3045INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3046{
3047 //zqiu: Please ignor signalIndex.
3048 if (NULL == SignalLevel)
3049 return RETURN_ERR;
3050 *SignalLevel=(radioIndex==0)?-19:-19;
3051
3052 return RETURN_OK;
3053}
3054
3055//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3056INT wifi_applyRadioSettings(INT radioIndex)
3057{
3058 return RETURN_OK;
3059}
3060
3061//Get the radio index assocated with this SSID entry
3062INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3063{
3064 if (NULL == radioIndex)
3065 return RETURN_ERR;
3066 *radioIndex=ssidIndex%2;
3067
3068 return RETURN_OK;
3069}
3070
3071//Device.WiFi.SSID.{i}.Enable
3072//Get SSID enable configuration parameters (not the SSID enable status)
3073INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3074{
3075 if (NULL == output_bool)
3076 return RETURN_ERR;
3077
3078 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3079 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3080 return wifi_getApEnable(ssidIndex, output_bool);
3081}
3082
3083//Device.WiFi.SSID.{i}.Enable
3084//Set SSID enable configuration parameters
3085INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3086{
3087 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3088 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3089 return wifi_setApEnable(ssidIndex, enable);
3090}
3091
3092//Device.WiFi.SSID.{i}.Status
3093//Get the SSID enable status
3094INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3095{
3096 char cmd[MAX_CMD_SIZE]={0};
3097 char buf[MAX_BUF_SIZE]={0};
3098 BOOL output_bool;
3099
3100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3101 if (NULL == output_string)
3102 return RETURN_ERR;
3103 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3104 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3105
3106 wifi_getApEnable(ssidIndex,&output_bool);
3107 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3108
3109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3110 return RETURN_OK;
3111}
3112
3113// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3114INT wifi_getSSIDName(INT apIndex, CHAR *output)
3115{
3116 char config_file[MAX_BUF_SIZE] = {0};
3117
3118 if (NULL == output)
3119 return RETURN_ERR;
3120
3121 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3122 wifi_hostapdRead(config_file,"ssid",output,32);
3123
3124 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3125 return RETURN_OK;
3126}
3127
3128// Set a max 32 byte string and sets an internal variable to the SSID name
3129INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3130{
3131 char str[MAX_BUF_SIZE]={'\0'};
3132 char cmd[MAX_CMD_SIZE]={'\0'};
3133 struct params params;
3134 char config_file[MAX_BUF_SIZE] = {0};
3135
3136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3137 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3138 return RETURN_ERR;
3139
3140 params.name = "ssid";
3141 params.value = ssid_string;
3142 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3143 wifi_hostapdWrite(config_file, &params, 1);
3144 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3146
3147 return RETURN_OK;
3148}
3149
3150//Get the BSSID
3151INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3152{
3153 char cmd[MAX_CMD_SIZE]="";
3154
3155 if (NULL == output_string)
3156 return RETURN_ERR;
3157
3158 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3159 {
3160 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3161 _syscmd(cmd, output_string, 64);
3162 return RETURN_OK;
3163 }
3164 strncpy(output_string, "\0", 1);
3165
3166 return RETURN_ERR;
3167}
3168
3169//Get the MAC address associated with this Wifi SSID
3170INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3171{
3172 wifi_getBaseBSSID(ssidIndex,output_string);
3173 return RETURN_OK;
3174}
3175
3176//Get the basic SSID traffic static info
3177//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3178//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3179INT wifi_applySSIDSettings(INT ssidIndex)
3180{
3181 BOOL status = false;
3182 char cmd[MAX_CMD_SIZE] = {0};
3183 char buf[MAX_CMD_SIZE] = {0};
3184 int apIndex, ret;
3185 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3186
3187 wifi_getApEnable(ssidIndex,&status);
3188 // Do not apply when ssid index is disabled
3189 if (status == false)
3190 return RETURN_OK;
3191
3192 /* Doing full remove and add for ssid Index
3193 * Not all hostapd options are supported with reload
3194 * for example macaddr_acl
3195 */
3196 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3197 return RETURN_ERR;
3198
3199 ret = wifi_setApEnable(ssidIndex,true);
3200
3201 /* Workaround for hostapd issue with multiple bss definitions
3202 * when first created interface will be removed
3203 * then all vaps other vaps on same phy are removed
3204 * after calling setApEnable to false readd all enabled vaps */
3205 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3206 apIndex = 2*i+radioIndex;
3207 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3208 _syscmd(cmd, buf, sizeof(buf));
3209 if(*buf == '1')
3210 wifi_setApEnable(apIndex, true);
3211 }
3212
3213 return ret;
3214}
3215
developera3c68b92022-09-13 15:27:29 +08003216struct channels_noise {
3217 int channel;
3218 int noise;
3219};
3220
3221// Return noise array for each channel
3222int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3223{
3224 FILE *f = NULL;
3225 char cmd[128] = {0};
3226 char *line = NULL;
3227 size_t len = 0;
3228 ssize_t read = 0;
3229 int tmp = 0, arr_index = -1;
3230
3231 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3232
3233 if ((f = popen(cmd, "r")) == NULL) {
3234 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3235 return RETURN_ERR;
3236 }
3237 line = malloc(sizeof(char) * 256);
3238 while((read = getline(&line, &len, f)) != -1) {
3239 sscanf(line, "%d", &tmp);
3240 if (tmp > 0) { // channel frequency, the first line must be frequency
3241 arr_index++;
3242 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3243 } else { // noise
3244 channels_noise_arr[arr_index].noise = tmp;
3245 }
3246 }
3247 free(line);
3248 pclose(f);
3249 return RETURN_OK;
3250}
3251
developer06a01d92022-09-07 16:32:39 +08003252//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3253//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3254INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3255{
developera3c68b92022-09-13 15:27:29 +08003256 int index = -1;
3257 wifi_neighbor_ap2_t *scan_array = NULL;
3258 char cmd[256]={0};
3259 char buf[128]={0};
3260 char file_name[32] = {0};
3261 char filter_SSID[32] = {0};
3262 int freq=0;
3263 FILE *f = NULL;
3264 size_t len=0;
3265 ssize_t read = 0;
3266 char *line =NULL;
3267 // int noise_arr[channels_num] = {0};
3268 int channels_num = 0;
3269 int vht_channel_width = 0;
3270 bool get_nosie_ret = false;
3271 bool filter_enable = false;
3272 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003273
3274 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003275
3276 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3277 f = fopen(file_name, "r");
3278 if (f != NULL) {
3279 fgets(filter_SSID, sizeof(file_name), f);
3280 if (strlen(filter_SSID) != 0)
3281 filter_enable = true;
3282 fclose(f);
3283 }
3284
3285 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003286 _syscmd(cmd, buf, sizeof(buf));
developera3c68b92022-09-13 15:27:29 +08003287 channels_num = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003288
developera3c68b92022-09-13 15:27:29 +08003289 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3290 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003291
developera3c68b92022-09-13 15:27:29 +08003292 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3293 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
3294 fprintf(stderr, "cmd: %s\n", cmd);
3295 if ((f = popen(cmd, "r")) == NULL) {
3296 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3297 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003298 }
developera3c68b92022-09-13 15:27:29 +08003299 line = malloc(sizeof(char) * 256);
3300 while ((read = getline(&line, &len, f)) != -1) {
3301 if(strstr(line, "BSS") != NULL) { // new neighbor info
3302 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3303 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3304 // 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 +08003305
developera3c68b92022-09-13 15:27:29 +08003306 if (!filter_BSS) {
3307 index++;
3308 wifi_neighbor_ap2_t *tmp;
3309 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3310 if (tmp == NULL) { // no more memory to use
3311 index--;
3312 wifi_dbg_printf("%s: realloc failed\n", __func__);
3313 break;
3314 }
3315 scan_array = tmp;
3316 }
3317 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3318
3319 filter_BSS = false;
3320 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3321 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3322 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3323 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3324 } else if (strstr(line, "freq") != NULL) {
3325 sscanf(line," freq: %d", &freq);
3326 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3327
3328 if (freq >= 2412 && freq <= 2484) {
3329 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3330 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3331 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3332 }
3333 else if (freq >= 5160 && freq <= 5805) {
3334 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3335 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3336 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3337 }
3338
3339 scan_array[index].ap_Noise = 0;
3340 if (get_nosie_ret) {
3341 for (int i = 0; i < channels_num; i++) {
3342 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3343 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3344 break;
3345 }
3346 }
3347 }
3348 } else if (strstr(line, "beacon interval") != NULL) {
3349 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3350 } else if (strstr(line, "signal") != NULL) {
3351 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3352 } else if (strstr(line,"SSID") != NULL) {
3353 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3354 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3355 filter_BSS = true;
3356 }
3357 } else if (strstr(line, "Supported rates") != NULL) {
3358 char SRate[80] = {0}, *tmp = NULL;
3359 memset(buf, 0, sizeof(buf));
3360 strcpy(SRate, line);
3361 tmp = strtok(SRate, ":");
3362 tmp = strtok(NULL, ":");
3363 strcpy(buf, tmp);
3364 memset(SRate, 0, sizeof(SRate));
3365
3366 tmp = strtok(buf, " \n");
3367 while (tmp != NULL) {
3368 strcat(SRate, tmp);
3369 if (SRate[strlen(SRate) - 1] == '*') {
3370 SRate[strlen(SRate) - 1] = '\0';
3371 }
3372 strcat(SRate, ",");
3373
3374 tmp = strtok(NULL, " \n");
3375 }
3376 SRate[strlen(SRate) - 1] = '\0';
3377 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3378 } else if (strstr(line, "DTIM") != NULL) {
3379 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3380 } else if (strstr(line, "VHT capabilities") != NULL) {
3381 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3382 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3383 } else if (strstr(line, "HT capabilities") != NULL) {
3384 strcat(scan_array[index].ap_SupportedStandards, ",n");
3385 strcpy(scan_array[index].ap_OperatingStandards, "n");
3386 } else if (strstr(line, "VHT operation") != NULL) {
3387 read = getline(&line, &len, f);
3388 sscanf(line," * channel width: %d", &vht_channel_width);
3389 if(vht_channel_width == 1) {
3390 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3391 } else {
3392 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3393 }
3394 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3395 continue;
3396 } else if (strstr(line, "HT operation") != NULL) {
3397 read = getline(&line, &len, f);
3398 sscanf(line," * secondary channel offset: %s", &buf);
3399 if (!strcmp(buf, "above")) {
3400 //40Mhz +
3401 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3402 }
3403 else if (!strcmp(buf, "below")) {
3404 //40Mhz -
3405 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3406 } else {
3407 //20Mhz
3408 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3409 }
3410 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3411 continue;
3412 } else if (strstr(line, "HE capabilities") != NULL) {
3413 strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax"));
3414 strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax"));
3415 } else if (strstr(line, "HE PHY Capabilities") != NULL) {
3416 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3417 if (strstr(line, "HE40/2.4GHz") != NULL)
3418 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS"));
3419 else
3420 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20"));
3421 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
3422 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support
3423 read = getline(&line, &len, f);
3424 if (strstr(line, "HE160/5GHz") != NULL)
3425 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160"));
3426 }
3427 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3428 continue;
3429 } else if (strstr(line, "WPA") != NULL) {
3430 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3431 } else if (strstr(line, "RSN") != NULL) {
3432 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3433 } else if (strstr(line, "Group cipher") != NULL) {
3434 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3435 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3436 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3437 }
3438 }
3439 }
3440
3441 if (!filter_BSS) {
3442 *output_array_size = index + 1;
3443 } else {
3444 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3445 *output_array_size = index;
3446 }
3447 *neighbor_ap_array = scan_array;
3448 free(line);
3449 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003451 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003452}
3453
3454//>> Deprecated: used for old RDKB code.
3455INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3456{
3457 INT status = RETURN_ERR;
3458
3459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3460 output_struct->wifi_PLCPErrorCount = 0;
3461 output_struct->wifi_FCSErrorCount = 0;
3462 output_struct->wifi_InvalidMACCount = 0;
3463 output_struct->wifi_PacketsOtherReceived = 0;
3464 output_struct->wifi_Noise = 0;
3465 status = RETURN_OK;
3466 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3467 return status;
3468}
3469
3470INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3471{
3472 char cmd[128];
3473 char buf[1280];
3474 char *pos = NULL;
3475
3476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3477 if (NULL == output_struct)
3478 return RETURN_ERR;
3479
3480 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3481
3482 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3483 _syscmd(cmd, buf, sizeof(buf));
3484
3485 pos = buf;
3486 if ((pos = strstr(pos, "RX packets:")) == NULL)
3487 return RETURN_ERR;
3488 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3489
3490 if ((pos = strstr(pos, "TX packets:")) == NULL)
3491 return RETURN_ERR;
3492 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3493
3494 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3495 return RETURN_ERR;
3496 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3497
3498 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3499 return RETURN_ERR;
3500 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3501
3502 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3503 _syscmd(cmd, buf, sizeof(buf));
3504 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3505
3506#if 0
3507 //TODO: need to revisit below implementation
3508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3509 char interface_name[MAX_BUF_SIZE] = {0};
3510 char interface_status[MAX_BUF_SIZE] = {0};
3511 char Value[MAX_BUF_SIZE] = {0};
3512 char buf[MAX_CMD_SIZE] = {0};
3513 char cmd[MAX_CMD_SIZE] = {0};
3514 FILE *fp = NULL;
3515
3516 if (NULL == output_struct) {
3517 return RETURN_ERR;
3518 }
3519
3520 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3521
3522 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3523 {
3524 if(apIndex == 0) //private_wifi for 2.4G
3525 {
3526 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3527 }
3528 else if(apIndex == 1) //private_wifi for 5G
3529 {
3530 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3531 }
3532 else if(apIndex == 4) //public_wifi for 2.4G
3533 {
3534 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3535 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3536 {
3537 return RETURN_ERR;
3538 }
3539 if(buf[0] == '#')//tp-link
3540 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3541 else//tenda
3542 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3543 }
3544 else if(apIndex == 5) //public_wifi for 5G
3545 {
3546 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3547 }
3548
3549 GetIfacestatus(interface_name, interface_status);
3550
3551 if(0 != strcmp(interface_status, "1"))
3552 return RETURN_ERR;
3553
3554 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3555 system(cmd);
3556
3557 fp = fopen("/tmp/SSID_Stats.txt", "r");
3558 if(fp == NULL)
3559 {
3560 printf("/tmp/SSID_Stats.txt not exists \n");
3561 return RETURN_ERR;
3562 }
3563 fclose(fp);
3564
3565 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3566 File_Reading(buf, Value);
3567 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3568
3569 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3570 File_Reading(buf, Value);
3571 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3572
3573 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3574 File_Reading(buf, Value);
3575 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3576
3577 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3578 File_Reading(buf, Value);
3579 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3580
3581 /* There is no specific parameter from caller to associate the value wifi_Associations */
3582 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3583 //_syscmd(cmd, buf, sizeof(buf));
3584 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3585 }
3586#endif
3587 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3588 return RETURN_OK;
3589}
3590
3591INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3592{
3593 char interface_name[MAX_BUF_SIZE] = {0};
3594 char interface_status[MAX_BUF_SIZE] = {0};
3595 char Value[MAX_BUF_SIZE] = {0};
3596 char buf[MAX_CMD_SIZE] = {0};
3597 char cmd[MAX_CMD_SIZE] = {0};
3598 FILE *fp = NULL;
3599
3600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3601 if (NULL == output_struct)
3602 return RETURN_ERR;
3603
3604 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3605
3606 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3607 {
3608 if(apIndex == 0) //private_wifi for 2.4G
3609 {
3610 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3611 }
3612 else if(apIndex == 1) //private_wifi for 5G
3613 {
3614 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3615 }
3616 else if(apIndex == 4) //public_wifi for 2.4G
3617 {
3618 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3619 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3620 {
3621 return RETURN_ERR;
3622 }
3623 if(buf[0] == '#')
3624 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3625 else
3626 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3627 }
3628 else if(apIndex == 5) //public_wifi for 5G
3629 {
3630 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3631 }
3632
3633 GetIfacestatus(interface_name, interface_status);
3634
3635 if(0 != strcmp(interface_status, "1"))
3636 return RETURN_ERR;
3637
3638 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3639 system(cmd);
3640
3641 fp = fopen("/tmp/SSID_Stats.txt", "r");
3642 if(fp == NULL)
3643 {
3644 printf("/tmp/SSID_Stats.txt not exists \n");
3645 return RETURN_ERR;
3646 }
3647 fclose(fp);
3648
3649 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3650 File_Reading(buf, Value);
3651 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3652
3653 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3654 File_Reading(buf, Value);
3655 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3656
3657 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3658 File_Reading(buf, Value);
3659 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3660
3661 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3662 File_Reading(buf, Value);
3663 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3664 }
3665
3666 output_struct->wifi_UnicastPacketsSent = 0;
3667 output_struct->wifi_UnicastPacketsReceived = 0;
3668 output_struct->wifi_MulticastPacketsSent = 0;
3669 output_struct->wifi_MulticastPacketsReceived = 0;
3670 output_struct->wifi_BroadcastPacketsSent = 0;
3671 output_struct->wifi_BroadcastPacketsRecevied = 0;
3672 output_struct->wifi_UnknownPacketsReceived = 0;
3673
3674 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3675 return RETURN_OK;
3676}
3677
3678INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3679{
3680 INT status = RETURN_ERR;
3681
3682 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3683 //Below values should get updated from hal
3684 output_struct->wifi_RetransCount=0;
3685 output_struct->wifi_FailedRetransCount=0;
3686 output_struct->wifi_RetryCount=0;
3687 output_struct->wifi_MultipleRetryCount=0;
3688 output_struct->wifi_ACKFailureCount=0;
3689 output_struct->wifi_AggregatedPacketCount=0;
3690
3691 status = RETURN_OK;
3692 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3693
3694 return status;
3695}
3696
3697INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
3698{
3699 INT status = RETURN_ERR;
3700 UINT index;
3701 wifi_neighbor_ap_t *pt=NULL;
3702
3703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3704 *output_array_size=2;
3705 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
3706 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
3707 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
3708 strcpy(pt->ap_Radio,"");
3709 strcpy(pt->ap_SSID,"");
3710 strcpy(pt->ap_BSSID,"");
3711 strcpy(pt->ap_Mode,"");
3712 pt->ap_Channel=1;
3713 pt->ap_SignalStrength=0;
3714 strcpy(pt->ap_SecurityModeEnabled,"");
3715 strcpy(pt->ap_EncryptionMode,"");
3716 strcpy(pt->ap_OperatingFrequencyBand,"");
3717 strcpy(pt->ap_SupportedStandards,"");
3718 strcpy(pt->ap_OperatingStandards,"");
3719 strcpy(pt->ap_OperatingChannelBandwidth,"");
3720 pt->ap_BeaconPeriod=1;
3721 pt->ap_Noise=0;
3722 strcpy(pt->ap_BasicDataTransferRates,"");
3723 strcpy(pt->ap_SupportedDataTransferRates,"");
3724 pt->ap_DTIMPeriod=1;
3725 pt->ap_ChannelUtilization = 1;
3726 }
3727
3728 status = RETURN_OK;
3729 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3730
3731 return status;
3732}
3733
3734//----------------- AP HAL -------------------------------
3735
3736//>> Deprecated: used for old RDKB code.
3737INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
3738{
3739 if (NULL == output_ulong || NULL == output_struct)
3740 return RETURN_ERR;
3741 *output_ulong = 0;
3742 *output_struct = NULL;
3743 return RETURN_OK;
3744}
3745
3746#ifdef HAL_NETLINK_IMPL
3747static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
3748 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3749 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3750 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
3751 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
3752 char mac_addr[20];
3753 static int count=0;
3754 int rate=0;
3755
3756 wifi_device_info_t *out = (wifi_device_info_t*)arg;
3757
3758 nla_parse(tb,
3759 NL80211_ATTR_MAX,
3760 genlmsg_attrdata(gnlh, 0),
3761 genlmsg_attrlen(gnlh, 0),
3762 NULL);
3763
3764 if(!tb[NL80211_ATTR_STA_INFO]) {
3765 fprintf(stderr, "sta stats missing!\n");
3766 return NL_SKIP;
3767 }
3768
3769
3770 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
3771 fprintf(stderr, "failed to parse nested attributes!\n");
3772 return NL_SKIP;
3773 }
3774
3775 //devIndex starts from 1
3776 if( ++count == out->wifi_devIndex )
3777 {
3778 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
3779 //Getting the mac addrress
3780 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
3781
3782 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
3783 fprintf(stderr, "failed to parse nested rate attributes!");
3784 return NL_SKIP;
3785 }
3786
3787 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
3788 if(rinfo[NL80211_RATE_INFO_BITRATE])
3789 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
3790 out->wifi_devTxRate = rate/10;
3791 }
3792
3793 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
3794 fprintf(stderr, "failed to parse nested rate attributes!");
3795 return NL_SKIP;
3796 }
3797
3798 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
3799 if(rinfo[NL80211_RATE_INFO_BITRATE])
3800 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
3801 out->wifi_devRxRate = rate/10;
3802 }
3803 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
3804 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
3805
3806 out->wifi_devAssociatedDeviceAuthentiationState = 1;
3807 count = 0; //starts the count for next cycle
3808 return NL_STOP;
3809 }
3810
3811 return NL_SKIP;
3812
3813}
3814#endif
3815
3816INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
3817{
3818#ifdef HAL_NETLINK_IMPL
3819 Netlink nl;
3820 char if_name[10];
3821
3822 wifi_device_info_t info;
3823 info.wifi_devIndex = devIndex;
3824
3825 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
3826
3827 nl.id = initSock80211(&nl);
3828
3829 if (nl.id < 0) {
3830 fprintf(stderr, "Error initializing netlink \n");
3831 return -1;
3832 }
3833
3834 struct nl_msg* msg = nlmsg_alloc();
3835
3836 if (!msg) {
3837 fprintf(stderr, "Failed to allocate netlink message.\n");
3838 nlfree(&nl);
3839 return -2;
3840 }
3841
3842 genlmsg_put(msg,
3843 NL_AUTO_PORT,
3844 NL_AUTO_SEQ,
3845 nl.id,
3846 0,
3847 NLM_F_DUMP,
3848 NL80211_CMD_GET_STATION,
3849 0);
3850
3851 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
3852 nl_send_auto(nl.socket, msg);
3853 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
3854 nl_recvmsgs(nl.socket, nl.cb);
3855 nlmsg_free(msg);
3856 nlfree(&nl);
3857
3858 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
3859 output_struct->wifi_devRxRate = info.wifi_devRxRate;
3860 output_struct->wifi_devTxRate = info.wifi_devTxRate;
3861 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
3862 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
3863 return RETURN_OK;
3864#else
3865 //iw utility to retrieve station information
3866#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
3867#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
3868#define MACFILE "/tmp/wifi_AssoMac.txt"
3869#define TXRATEFILE "/tmp/wifi_txrate.txt"
3870#define RXRATEFILE "/tmp/wifi_rxrate.txt"
3871 FILE *file = NULL;
3872 char if_name[10] = {'\0'};
3873 char pipeCmd[256] = {'\0'};
3874 char line[256];
3875 int count,device = 0;
3876
3877 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
3878
3879 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
3880 file = popen(pipeCmd, "r");
3881
3882 if(file == NULL)
3883 return RETURN_ERR; //popen failed
3884
3885 fgets(line, sizeof line, file);
3886 device = atoi(line);
3887 pclose(file);
3888
3889 if(device == 0)
3890 return RETURN_ERR; //No devices are connected
3891
3892 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
3893 system(pipeCmd);
3894
3895 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
3896
3897 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
3898
3899 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
3900
3901 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
3902
3903 //devIndex starts from 1, ++count
3904 if((file = fopen(SIGNALFILE, "r")) != NULL )
3905 {
3906 for(count =0;fgets(line, sizeof line, file) != NULL;)
3907 {
3908 if (++count == devIndex)
3909 {
3910 output_struct->wifi_devSignalStrength = atoi(line);
3911 break;
3912 }
3913 }
3914 fclose(file);
3915 }
3916 else
3917 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
3918
3919 if((file = fopen(MACFILE, "r")) != NULL )
3920 {
3921 for(count =0;fgets(line, sizeof line, file) != NULL;)
3922 {
3923 if (++count == devIndex)
3924 {
3925 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]);
3926 break;
3927 }
3928 }
3929 fclose(file);
3930 }
3931 else
3932 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
3933
3934 if((file = fopen(TXRATEFILE, "r")) != NULL )
3935 {
3936 for(count =0;fgets(line, sizeof line, file) != NULL;)
3937 {
3938 if (++count == devIndex)
3939 {
3940 output_struct->wifi_devTxRate = atoi(line);
3941 break;
3942 }
3943 }
3944 fclose(file);
3945 }
3946 else
3947 fprintf(stderr,"fopen wifi_txrate.txt failed");
3948
3949 if((file = fopen(RXRATEFILE, "r")) != NULL)
3950 {
3951 for(count =0;fgets(line, sizeof line, file) != NULL;)
3952 {
3953 if (++count == devIndex)
3954 {
3955 output_struct->wifi_devRxRate = atoi(line);
3956 break;
3957 }
3958 }
3959 fclose(file);
3960 }
3961 else
3962 fprintf(stderr,"fopen wifi_rxrate.txt failed");
3963
3964 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
3965
3966 return RETURN_OK;
3967#endif
3968}
3969
3970INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
3971{
3972 if (NULL == device)
3973 return RETURN_ERR;
3974 return RETURN_OK;
3975}
3976//<<
3977
3978
3979//--------------wifi_ap_hal-----------------------------
3980//enables CTS protection for the radio used by this AP
3981INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
3982{
3983 //save config and Apply instantly
3984 return RETURN_ERR;
3985}
3986
3987// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
3988INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
3989{
developer463d39a2022-09-13 15:32:51 +08003990 char config_file[64] = {'\0'};
3991 char buf[64] = {'\0'};
3992 struct params list;
3993
3994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3995 list.name = "ht_coex";
3996 snprintf(buf, sizeof(buf), "%d", enable);
3997 list.value = buf;
3998
3999 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4000 wifi_hostapdWrite(config_file, &list, 1);
4001 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4002
4003 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4004
4005 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004006}
4007
4008//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4009INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4010{
developerea4bcce2022-09-13 15:26:13 +08004011 char config_file[MAX_BUF_SIZE] = {'\0'};
4012 char buf[MAX_BUF_SIZE] = {'\0'};
4013 struct params list;
4014
4015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4016 if (threshold < 256 || threshold > 2346 )
4017 return RETURN_ERR;
4018 list.name = "fragm_threshold";
4019 snprintf(buf, sizeof(buf), "%d", threshold);
4020 list.value = buf;
4021
4022 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4023 wifi_hostapdWrite(config_file, &list, 1);
4024 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004025
developerea4bcce2022-09-13 15:26:13 +08004026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004027
4028 return RETURN_OK;
4029}
4030
4031// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4032INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4033{
developer51a927d2022-09-13 15:42:22 +08004034 char config_file[64] = {'\0'};
4035 char cmd[128] = {'\0'};
4036 char buf[64] = {'\0'};
4037 char stbc_config[16] = {'\0'};
4038 wifi_band band;
4039 int iterator = 0;
4040 BOOL current_stbc = FALSE;
4041
4042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4043
4044 band = wifi_index_to_band(radioIndex);
4045 if (band == band_invalid)
4046 return RETURN_ERR;
4047
4048 if (band == band_2_4)
4049 iterator = 1;
4050 else if (band == band_5)
4051 iterator = 2;
4052 else
4053 return RETURN_OK;
4054
4055 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4056
4057 // set ht and vht config
4058 for (int i = 0; i < iterator; i++) {
4059 memset(stbc_config, 0, sizeof(stbc_config));
4060 memset(cmd, 0, sizeof(cmd));
4061 memset(buf, 0, sizeof(buf));
4062 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4063 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4064 _syscmd(cmd, buf, sizeof(buf));
4065 if (strlen(buf) != 0)
4066 current_stbc = TRUE;
4067 if (current_stbc == STBC_Enable)
4068 continue;
4069
4070 if (STBC_Enable == TRUE) {
4071 // Append the STBC flags in capab config
4072 memset(cmd, 0, sizeof(cmd));
4073 if (i == 0)
4074 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4075 else
4076 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4077 _syscmd(cmd, buf, sizeof(buf));
4078 } else if (STBC_Enable == FALSE) {
4079 // Remove the STBC flags and remain other flags in capab
4080 memset(cmd, 0, sizeof(cmd));
4081 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4082 _syscmd(cmd, buf, sizeof(buf));
4083 memset(cmd, 0, sizeof(cmd));
4084 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4085 _syscmd(cmd, buf, sizeof(buf));
4086 }
4087 }
4088
4089 wifi_reloadAp(radioIndex);
4090
4091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4092 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004093}
4094
4095// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4096INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4097{
4098 return RETURN_ERR;
4099}
4100
4101// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4102INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4103{
4104 //Apply instantly
4105 return RETURN_ERR;
4106}
4107
4108//P2 // outputs the number of Tx streams
4109INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4110{
4111 return RETURN_ERR;
4112}
4113
4114//P2 // sets the number of Tx streams to an enviornment variable
4115INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4116{
4117 //save to wifi config, wait for wifi reset or wifi_pushTxChainMask to apply
4118 return RETURN_ERR;
4119}
4120
4121//P2 // outputs the number of Rx streams
4122INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4123{
4124 if (NULL == output_int)
4125 return RETURN_ERR;
4126 *output_int = 1;
4127 return RETURN_OK;
4128}
4129
4130//P2 // sets the number of Rx streams to an enviornment variable
4131INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4132{
4133 //save to wifi config, wait for wifi reset or wifi_pushRxChainMask to apply
4134 return RETURN_ERR;
4135}
4136
4137//Get radio RDG enable setting
4138INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4139{
4140 if (NULL == output_bool)
4141 return RETURN_ERR;
4142 *output_bool = TRUE;
4143 return RETURN_OK;
4144}
4145
4146//Get radio RDG enable setting
4147INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4148{
4149 if (NULL == output_bool)
4150 return RETURN_ERR;
4151 *output_bool = TRUE;
4152 return RETURN_OK;
4153}
4154
4155//Set radio RDG enable setting
4156INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4157{
4158 return RETURN_ERR;
4159}
4160
4161//Get radio ADDBA enable setting
4162INT wifi_getRadioDeclineBARequestEnable(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//Set radio ADDBA enable setting
4171INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4172{
4173 return RETURN_ERR;
4174}
4175
4176//Get radio auto block ack enable setting
4177INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4178{
4179 if (NULL == output_bool)
4180 return RETURN_ERR;
4181 *output_bool = TRUE;
4182 return RETURN_OK;
4183}
4184
4185//Set radio auto block ack enable setting
4186INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4187{
4188 return RETURN_ERR;
4189}
4190
4191//Get radio 11n pure mode enable support
4192INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4193{
4194 if (NULL == output_bool)
4195 return RETURN_ERR;
4196 *output_bool = TRUE;
4197 return RETURN_OK;
4198}
4199
4200//Get radio 11n pure mode enable setting
4201INT wifi_getRadio11nGreenfieldEnable(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 11n pure mode enable setting
4210INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4211{
4212 return RETURN_ERR;
4213}
4214
4215//Get radio IGMP snooping enable setting
4216INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4217{
developer81bf2ed2022-09-13 15:31:14 +08004218 char cmd[128]={0};
4219 char buf[4]={0};
4220 bool bridge = FALSE, mac80211 = FALSE;
4221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4222
4223 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004224 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004225
4226 *output_bool = FALSE;
4227
4228 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4229 _syscmd(cmd, buf, sizeof(buf));
4230 if (strncmp(buf, "1", 1) == 0)
4231 bridge = TRUE;
4232
4233 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4234 _syscmd(cmd, buf, sizeof(buf));
4235 if (strncmp(buf, "1", 1) == 0)
4236 mac80211 = TRUE;
4237
4238 if (bridge && mac80211)
4239 *output_bool = TRUE;
4240
4241 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004242 return RETURN_OK;
4243}
4244
4245//Set radio IGMP snooping enable setting
4246INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4247{
developer81bf2ed2022-09-13 15:31:14 +08004248 char cmd[128]={0};
4249 char buf[4]={0};
4250
4251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4252
4253 // bridge
4254 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4255 _syscmd(cmd, buf, sizeof(buf));
4256
4257 // mac80211
4258 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4259 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4260 _syscmd(cmd, buf, sizeof(buf));
4261 }
4262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4263 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004264}
4265
4266//Get the Reset count of radio
4267INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4268{
4269 if (NULL == output_int)
4270 return RETURN_ERR;
4271 *output_int = (radioIndex==0)? 1: 3;
4272
4273 return RETURN_OK;
4274}
4275
4276
4277//---------------------------------------------------------------------------------------------------
4278//
4279// Additional Wifi AP level APIs used for Access Point devices
4280//
4281//---------------------------------------------------------------------------------------------------
4282
4283// creates a new ap and pushes these parameters to the hardware
4284INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4285{
4286 char buf[1024];
4287 char cmd[128];
4288
4289 if (NULL == essid)
4290 return RETURN_ERR;
4291
4292 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4293 _syscmd(cmd, buf, sizeof(buf));
4294
4295 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4296 _syscmd(cmd, buf, sizeof(buf));
4297
4298 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4299
4300 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4301 _syscmd(cmd, buf, sizeof(buf));
4302
4303 return RETURN_OK;
4304}
4305
4306// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4307INT wifi_deleteAp(INT apIndex)
4308{
4309 char buf[1024];
4310 char cmd[128];
4311
4312 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4313 _syscmd(cmd, buf, sizeof(buf));
4314
4315 wifi_removeApSecVaribles(apIndex);
4316
4317 return RETURN_OK;
4318}
4319
4320// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4321INT wifi_getApName(INT apIndex, CHAR *output_string)
4322{
4323 if(NULL == output_string)
4324 return RETURN_ERR;
4325
4326 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4327 return RETURN_OK;
4328}
4329
4330// Outputs the index number in that corresponds to the SSID string
4331INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4332{
4333 CHAR *pos = NULL;
4334
4335 *output_int = -1;
4336 pos = strstr(inputSsidString, AP_PREFIX);
4337 if(pos)
4338 {
4339 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4340 return RETURN_OK;
4341 }
4342 return RETURN_ERR;
4343}
4344
4345INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4346{
4347 return wifi_getIndexFromName(inputSsidString, output_int);
4348}
4349
4350// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4351INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4352{
4353 char buf[MAX_BUF_SIZE] = {0};
4354 char cmd[MAX_CMD_SIZE] = {0};
4355 char config_file[MAX_BUF_SIZE] = {0};
4356
4357 if(NULL == output_string)
4358 return RETURN_ERR;
4359
4360 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4361 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4362 if((strcmp(buf,"3")==0))
4363 snprintf(output_string, 32, "WPAand11i");
4364 else if((strcmp(buf,"2")==0))
4365 snprintf(output_string, 32, "11i");
4366 else if((strcmp(buf,"1")==0))
4367 snprintf(output_string, 32, "WPA");
4368 else
4369 snprintf(output_string, 32, "None");
4370
4371 return RETURN_OK;
4372}
4373
4374// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4375INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4376{
4377 char config_file[MAX_BUF_SIZE] = {0};
4378 struct params list;
4379
4380 if (NULL == beaconTypeString)
4381 return RETURN_ERR;
4382 list.name = "wpa";
4383 list.value = "0";
4384
4385 if((strcmp(beaconTypeString,"WPAand11i")==0))
4386 list.value="3";
4387 else if((strcmp(beaconTypeString,"11i")==0))
4388 list.value="2";
4389 else if((strcmp(beaconTypeString,"WPA")==0))
4390 list.value="1";
4391
4392 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4393 wifi_hostapdWrite(config_file, &list, 1);
4394 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4395 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4396 return RETURN_OK;
4397}
4398
4399// sets the beacon interval on the hardware for this AP
4400INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4401{
developer5f222492022-09-13 15:21:52 +08004402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4403 struct params params={'\0'};
4404 char buf[MAX_BUF_SIZE] = {'\0'};
4405 char config_file[MAX_BUF_SIZE] = {'\0'};
4406
4407 params.name = "beacon_int";
4408 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4409 params.value = buf;
4410
4411 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4412 wifi_hostapdWrite(config_file, &params, 1);
4413
4414 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4415 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4416 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004417}
4418
4419INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4420{
4421 //save config and apply instantly
4422 return RETURN_ERR;
4423}
4424
4425// Get the packet size threshold supported.
4426INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4427{
4428 //save config and apply instantly
4429 if (NULL == output_bool)
4430 return RETURN_ERR;
4431 *output_bool = FALSE;
4432 return RETURN_OK;
4433}
4434
4435// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4436INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4437{
4438 char cmd[128];
4439 char buf[512];
4440
4441 if (threshold > 0)
4442 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4443 else
4444 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4445 _syscmd(cmd, buf, sizeof(buf));
4446
4447 return RETURN_OK;
4448}
4449
4450// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4451INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4452{
4453 if (NULL == output_string)
4454 return RETURN_ERR;
4455 snprintf(output_string, 32, "TKIPandAESEncryption");
4456 return RETURN_OK;
4457
4458}
4459
4460// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4461INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4462{
4463 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4464 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4465
4466 if(NULL == output_string)
4467 return RETURN_ERR;
4468
4469 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4470 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4471
4472 if(strcmp(buf,"0")==0)
4473 {
4474 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4475 snprintf(output_string, 32, "None");
4476 return RETURN_OK;
4477 }
4478 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4479 param_name = "rsn_pairwise";
4480 else if((strcmp(buf,"1")==0))
4481 param_name = "wpa_pairwise";
4482 else
4483 return RETURN_ERR;
4484 memset(output_string,'\0',32);
4485 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4486 wifi_hostapdRead(config_file,param_name,output_string,32);
4487 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4488
4489 if(strcmp(output_string,"TKIP") == 0)
4490 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4491 else if(strcmp(output_string,"CCMP") == 0)
4492 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4493 else if(strcmp(output_string,"TKIP CCMP") == 0)
4494 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4495
4496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4497 return RETURN_OK;
4498}
4499
4500// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4501INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4502{
4503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4504 struct params params={'\0'};
4505 char output_string[32];
4506 char config_file[MAX_BUF_SIZE] = {0};
4507
4508 memset(output_string,'\0',32);
4509 wifi_getApWpaEncryptionMode(apIndex,output_string);
4510
4511 if(strcmp(encMode, "TKIPEncryption") == 0)
4512 params.value = "TKIP";
4513 else if(strcmp(encMode,"AESEncryption") == 0)
4514 params.value = "CCMP";
4515 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4516 params.value = "TKIP CCMP";
4517
4518 if((strcmp(output_string,"WPAand11i")==0))
4519 {
4520 params.name = "wpa_pairwise";
4521 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4522 wifi_hostapdWrite(config_file, &params, 1);
4523 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4524
4525 params.name,"rsn_pairwise";
4526 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4527 wifi_hostapdWrite(config_file, &params, 1);
4528 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4529
4530 return RETURN_OK;
4531 }
4532 else if((strcmp(output_string,"11i")==0))
4533 {
4534 params.name = "rsn_pairwise";
4535 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4536 wifi_hostapdWrite(config_file, &params, 1);
4537 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4538 return RETURN_OK;
4539 }
4540 else if((strcmp(output_string,"WPA")==0))
4541 {
4542 params.name = "wpa_pairwise";
4543 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4544 wifi_hostapdWrite(config_file, &params, 1);
4545 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4546 return RETURN_OK;
4547 }
4548
4549 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4550 return RETURN_OK;
4551}
4552
4553// deletes internal security varable settings for this ap
4554INT wifi_removeApSecVaribles(INT apIndex)
4555{
4556 //TODO: remove the entry in hostapd config file
4557 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4558 //_syscmd(cmd, buf, sizeof(buf));
4559
4560 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4561 //_syscmd(cmd, buf, sizeof(buf));
4562 return RETURN_ERR;
4563}
4564
4565// changes the hardware settings to disable encryption on this ap
4566INT wifi_disableApEncryption(INT apIndex)
4567{
4568 //Apply instantly
4569 return RETURN_ERR;
4570}
4571
4572// set the authorization mode on this ap
4573// mode mapping as: 1: open, 2: shared, 4:auto
4574INT wifi_setApAuthMode(INT apIndex, INT mode)
4575{
4576 //Apply instantly
4577 return RETURN_ERR;
4578}
4579
4580// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4581INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4582{
4583 //save to wifi config, and wait for wifi restart to apply
4584 struct params params={'\0'};
4585 char config_file[MAX_BUF_SIZE] = {0};
4586 int ret;
4587
4588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4589 if(authMode == NULL)
4590 return RETURN_ERR;
4591
4592 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4593 params.name = "wpa_key_mgmt";
4594
4595 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4596 params.value = "WPA-PSK";
4597 else if(strcmp(authMode,"EAPAuthentication") == 0)
4598 params.value = "WPA-EAP";
4599 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4600 return RETURN_OK; //This is taken careof in beaconType
4601
4602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4603 ret=wifi_hostapdWrite(config_file,&params,1);
4604 if(!ret)
4605 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4607
4608 return ret;
4609}
4610
4611// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4612INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4613{
4614 //save to wifi config, and wait for wifi restart to apply
4615 char BeaconType[50] = {0};
4616 char config_file[MAX_BUF_SIZE] = {0};
4617
4618 *authMode = 0;
4619 wifi_getApBeaconType(apIndex,BeaconType);
4620 printf("%s____%s \n",__FUNCTION__,BeaconType);
4621
4622 if(strcmp(BeaconType,"None") == 0)
4623 strcpy(authMode,"None");
4624 else
4625 {
4626 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4627 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4628 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4629 if(strcmp(authMode,"WPA-PSK") == 0)
4630 strcpy(authMode,"SharedAuthentication");
4631 else if(strcmp(authMode,"WPA-EAP") == 0)
4632 strcpy(authMode,"EAPAuthentication");
4633 }
4634
4635 return RETURN_OK;
4636}
4637
4638// Outputs the number of stations associated per AP
4639INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4640{
4641 char cmd[128]={0};
4642 char buf[128]={0};
4643 BOOL status = false;
4644
4645 if(apIndex > MAX_APS)
4646 return RETURN_ERR;
4647
4648 wifi_getApEnable(apIndex,&status);
4649 if (!status)
4650 return RETURN_OK;
4651
4652 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4653 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4654 _syscmd(cmd, buf, sizeof(buf));
4655 sscanf(buf,"%lu", output_ulong);
4656
4657 return RETURN_OK;
4658}
4659
4660// manually removes any active wi-fi association with the device specified on this ap
4661INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4662{
4663 char buf[126]={'\0'};
4664
4665 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4666 system(buf);
4667
4668 return RETURN_OK;
4669}
4670
4671// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4672INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4673{
4674 if(NULL == output_int)
4675 return RETURN_ERR;
4676 *output_int = apIndex%2;
4677 return RETURN_OK;
4678}
4679
4680// sets the radio index for the specific ap
4681INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4682{
4683 //set to config only and wait for wifi reset to apply settings
4684 return RETURN_ERR;
4685}
4686
4687// Get the ACL MAC list per AP
4688INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4689{
4690 char cmd[MAX_CMD_SIZE]={'\0'};
4691 int ret = 0;
4692
4693 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4694 ret = _syscmd(cmd,macArray,buf_size);
4695 if (ret != 0)
4696 return RETURN_ERR;
4697
4698 return RETURN_OK;
4699}
4700
developere6aafda2022-09-13 14:59:28 +08004701INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4702{
4703 char cmd[MAX_CMD_SIZE]={'\0'};
4704 int ret = 0;
4705
4706 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4707 ret = _syscmd(cmd,macArray,buf_size);
4708 if (ret != 0)
4709 return RETURN_ERR;
4710
4711 return RETURN_OK;
4712}
4713
4714
developer06a01d92022-09-07 16:32:39 +08004715// Get the list of stations associated per AP
4716INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4717{
4718 char cmd[128];
4719
4720 if(apIndex > 3) //Currently supporting apIndex upto 3
4721 return RETURN_ERR;
4722 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
4723 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
4724 _syscmd(cmd, macArray, buf_size);
4725
4726 return RETURN_OK;
4727}
4728
4729// adds the mac address to the filter list
4730//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4731INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4732{
4733 char cmd[MAX_CMD_SIZE]={'\0'};
4734 char buf[MAX_BUF_SIZE]={'\0'};
4735
4736#if 0
4737 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4738 if(_syscmd(cmd,buf,sizeof(buf)))
4739 return RETURN_ERR;
4740#endif
4741 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
4742 if(_syscmd(cmd,buf,sizeof(buf)))
4743 return RETURN_ERR;
4744
4745 return RETURN_OK;
4746}
4747
4748// deletes the mac address from the filter list
4749//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4750INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4751{
4752 char cmd[MAX_CMD_SIZE]={'\0'};
4753 char buf[MAX_BUF_SIZE]={'\0'};
4754
4755#if 0
4756 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4757 if(_syscmd(cmd,buf,sizeof(buf)))
4758 return RETURN_ERR;
4759
4760#endif
4761 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
4762 if(_syscmd(cmd,buf,sizeof(buf)))
4763 return RETURN_ERR;
4764
4765 return RETURN_OK;
4766}
4767
4768// outputs the number of devices in the filter list
4769INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
4770{
developere6aafda2022-09-13 14:59:28 +08004771 char cmd[MAX_BUF_SIZE]={0};
4772 char buf[MAX_CMD_SIZE]={0};
4773
4774 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4775 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08004776 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08004777
4778 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
4779 _syscmd(cmd, buf, sizeof(buf));
4780
4781 *output_uint = atoi(buf);
4782
4783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4784 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004785}
4786
4787INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
4788{
4789 char cmd[128]={'\0'};
4790 char buf[128]={'\0'};
4791
4792 if(strcmp(action,"DENY")==0)
4793 {
4794 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
4795 system(buf);
4796 return RETURN_OK;
4797 }
4798
4799 if(strcmp(action,"ALLOW")==0)
4800 {
4801 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
4802 system(buf);
4803 return RETURN_OK;
4804 }
4805
4806 return RETURN_ERR;
4807
4808}
4809
4810// enable kick for devices on acl black list
4811INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
4812{
4813 char aclArray[512] = {0}, *acl = NULL;
4814 char assocArray[512] = {0}, *asso = NULL;
4815
developere6aafda2022-09-13 14:59:28 +08004816 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08004817 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
4818
4819 // if there are no devices connected there is nothing to do
4820 if (strlen(assocArray) < 17)
4821 return RETURN_OK;
4822
4823 if (enable == TRUE)
4824 {
4825 //kick off the MAC which is in ACL array (deny list)
4826 acl = strtok(aclArray, "\r\n");
4827 while (acl != NULL) {
4828 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
4829 wifi_kickApAssociatedDevice(apIndex, acl);
4830
4831 acl = strtok(NULL, "\r\n");
4832 }
developere6aafda2022-09-13 14:59:28 +08004833 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08004834 }
4835 else
4836 {
developere6aafda2022-09-13 14:59:28 +08004837 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08004838 }
4839
4840#if 0
4841 //TODO: need to revisit below implementation
4842 char aclArray[512]={0}, *acl=NULL;
4843 char assocArray[512]={0}, *asso=NULL;
4844 char buf[256]={'\0'};
4845 char action[10]={'\0'};
4846 FILE *fr=NULL;
4847 char interface[10]={'\0'};
4848 char config_file[MAX_BUF_SIZE] = {0};
4849
4850 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
4851 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
4852 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4853 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
4854
4855 sprintf(buf,"iptables -F WifiServices%d",apIndex);
4856 system(buf);
4857 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
4858 system(buf);
4859 sprintf(buf,"iptables -X WifiServices%d",apIndex);
4860 system(buf);
4861 sprintf(buf,"iptables -N WifiServices%d",apIndex);
4862 system(buf);
4863 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
4864 system(buf);
4865
4866 if ( enable == TRUE )
4867 {
4868 int device_count=0;
4869 strcpy(action,"DENY");
4870 //kick off the MAC which is in ACL array (deny list)
4871 acl = strtok (aclArray,",");
4872 while (acl != NULL) {
4873 if(strlen(acl)>=17)
4874 {
4875 apply_rules(apIndex, acl,action,interface);
4876 device_count++;
4877 //Register mac to be blocked ,in syscfg.db persistent storage
4878 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
4879 system(buf);
4880 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
4881 system(buf);
4882 system("syscfg commit");
4883
4884 wifi_kickApAssociatedDevice(apIndex, acl);
4885 }
4886 acl = strtok (NULL, ",");
4887 }
4888 }
4889 else
4890 {
4891 int device_count=0;
4892 char cmdmac[20]={'\0'};
4893 strcpy(action,"ALLOW");
4894 //kick off the MAC which is not in ACL array (allow 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 Allowed ,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 sprintf(cmdmac,"%s",acl);
4907 }
4908 acl = strtok (NULL, ",");
4909 }
4910 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
4911 system(buf);
4912
4913 //Disconnect the mac which is not in ACL
4914 asso = strtok (assocArray,",");
4915 while (asso != NULL) {
4916 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
4917 wifi_kickApAssociatedDevice(apIndex, asso);
4918 asso = strtok (NULL, ",");
4919 }
4920 }
4921#endif
4922 return RETURN_OK;
4923}
4924
4925INT wifi_setPreferPrivateConnection(BOOL enable)
4926{
4927 char interface_name[100] = {0},ssid_cur_value[50] = {0};
4928 char buf[1024] = {0};
4929
4930 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
4931 if(enable == TRUE)
4932 {
4933 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4934 sprintf(buf,"ifconfig %s down" ,interface_name);
4935 system(buf);
4936 memset(buf,0,sizeof(buf));
4937 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4938 sprintf(buf,"ifconfig %s down" ,interface_name);
4939 system(buf);
4940 }
4941 else
4942 {
4943 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
4944 if(strcmp(ssid_cur_value,"1") == 0)
4945 wifi_RestartPrivateWifi_5G();
4946 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
4947 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
4948 if(strcmp(ssid_cur_value,"1") == 0)
4949 wifi_RestartHostapd_2G();
4950 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
4951 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
4952 if(strcmp(ssid_cur_value,"1") == 0)
4953 wifi_RestartHostapd_5G();
4954 }
4955 return RETURN_OK;
4956}
4957
4958// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
4959INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
4960{
4961 int items = 1;
4962 struct params list[2];
4963 char buf[MAX_BUF_SIZE] = {0};
4964 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08004965 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08004966
4967 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08004968
developer10adcc12022-09-13 14:39:17 +08004969 if (filterMode == 0) {
4970 sprintf(buf, "%d", 0);
4971 list[0].value = buf;
4972
4973 char cmd[128], rtn[128];
4974 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
4975 _syscmd(cmd, rtn, sizeof(rtn));
4976 memset(cmd,0,sizeof(cmd));
4977 // Delete deny_mac_file in hostapd configuration
4978 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
4979 _syscmd(cmd, rtn, sizeof(rtn));
4980 }
4981 else if (filterMode == 1) {
4982 sprintf(buf, "%d", filterMode);
4983 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08004984 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
4985 list[1].name = "accept_mac_file";
4986 list[1].value = acl_file;
4987 items = 2;
developer10adcc12022-09-13 14:39:17 +08004988 } else if (filterMode == 2) {
4989 //TODO: deny_mac_file
4990 sprintf(buf, "%d", 0);
4991 list[0].value = buf;
4992 list[1].name = "deny_mac_file";
4993 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
4994 list[1].value = deny_file;
4995 items = 2;
4996 } else {
4997 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004998 }
developer10adcc12022-09-13 14:39:17 +08004999
developer06a01d92022-09-07 16:32:39 +08005000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5001 wifi_hostapdWrite(config_file, list, items);
5002
5003 return RETURN_OK;
5004
5005#if 0
5006 if(apIndex==0 || apIndex==1)
5007 {
5008 //set the filtermode
5009 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5010 system(buf);
5011 system("syscfg commit");
5012
5013 if(filterMode==0)
5014 {
5015 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5016 system(buf);
5017 return RETURN_OK;
5018 }
5019 }
5020 return RETURN_OK;
5021#endif
5022}
5023
5024// 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.
5025INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5026{
5027 return RETURN_ERR;
5028}
5029
5030// gets the vlan ID for this ap from an internal enviornment variable
5031INT wifi_getApVlanID(INT apIndex, INT *output_int)
5032{
5033 if(apIndex=0)
5034 {
5035 *output_int=100;
5036 return RETURN_OK;
5037 }
5038
5039 return RETURN_ERR;
5040}
5041
5042// sets the vlan ID for this ap to an internal enviornment variable
5043INT wifi_setApVlanID(INT apIndex, INT vlanId)
5044{
5045 //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)
5046 return RETURN_ERR;
5047}
5048
5049// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5050INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5051{
5052 snprintf(bridgeName, 32, "brlan0");
5053 snprintf(IP, 32, "10.0.0.1");
5054 snprintf(subnet, 32, "255.255.255.0");
5055
5056 return RETURN_OK;
5057}
5058
5059//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5060INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5061{
5062 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5063 return RETURN_ERR;
5064}
5065
5066// reset the vlan configuration for this ap
5067INT wifi_resetApVlanCfg(INT apIndex)
5068{
5069 //TODO: remove existing vlan for this ap
5070
5071 //Reapply vlan settings
5072 wifi_pushBridgeInfo(apIndex);
5073
5074 return RETURN_ERR;
5075}
5076
5077// 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.
5078INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5079{
5080 return RETURN_ERR;
5081}
5082
5083// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5084INT wifi_startHostApd()
5085{
5086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5087 system("systemctl start hostapd.service");
5088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5089 return RETURN_OK;
5090 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5091}
5092
5093// stops hostapd
5094INT wifi_stopHostApd()
5095{
5096 char cmd[128] = {0};
5097 char buf[128] = {0};
5098
5099 sprintf(cmd,"systemctl stop hostapd");
5100 _syscmd(cmd, buf, sizeof(buf));
5101
5102 return RETURN_OK;
5103}
5104
5105// restart hostapd dummy function
5106INT wifi_restartHostApd()
5107{
5108 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5109 system("systemctl restart hostapd-global");
5110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5111
5112 return RETURN_OK;
5113}
5114
5115static int align_hostapd_config(int index)
5116{
5117 ULONG lval;
5118 wifi_getRadioChannel(index%2, &lval);
5119 wifi_setRadioChannel(index%2, lval);
5120}
5121
5122// sets the AP enable status variable for the specified ap.
5123INT wifi_setApEnable(INT apIndex, BOOL enable)
5124{
5125 char config_file[MAX_BUF_SIZE] = {0};
5126 char cmd[MAX_CMD_SIZE] = {0};
5127 char buf[MAX_BUF_SIZE] = {0};
5128 BOOL status;
5129
5130 wifi_getApEnable(apIndex,&status);
5131 if (enable == status)
5132 return RETURN_OK;
5133
5134 if (enable == TRUE) {
5135 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5136 align_hostapd_config(apIndex);
5137 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5138 //Hostapd will bring up this interface
5139 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5140 _syscmd(cmd, buf, sizeof(buf));
5141 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5142 _syscmd(cmd, buf, sizeof(buf));
5143 }
5144 else {
5145 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5146 _syscmd(cmd, buf, sizeof(buf));
5147 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5148 _syscmd(cmd, buf, sizeof(buf));
5149 }
5150 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5151 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5152 _syscmd(cmd, buf, sizeof(buf));
5153 //Wait for wifi up/down to apply
5154 return RETURN_OK;
5155}
5156
5157// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5158INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5159{
5160 char cmd[MAX_CMD_SIZE] = {'\0'};
5161 char buf[MAX_BUF_SIZE] = {'\0'};
5162
5163 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5164 return RETURN_ERR;
5165
5166 *output_bool = 0;
5167
5168 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5169 {
5170 sprintf(cmd, "%s%s%d%s", "ifconfig ", AP_PREFIX, apIndex, " | grep UP");
5171 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5172 }
5173
5174 return RETURN_OK;
5175}
5176
5177// Outputs the AP "Enabled" "Disabled" status from driver
5178INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5179{
5180 char cmd[128] = {0};
5181 char buf[128] = {0};
5182 BOOL output_bool;
5183
5184 if ( NULL == output_string)
5185 return RETURN_ERR;
5186 wifi_getApEnable(apIndex,&output_bool);
5187
5188 if(output_bool == 1)
5189 snprintf(output_string, 32, "Up");
5190 else
5191 snprintf(output_string, 32, "Disable");
5192
5193 return RETURN_OK;
5194}
5195
5196//Indicates whether or not beacons include the SSID name.
5197// outputs a 1 if SSID on the AP is enabled, else outputs 0
5198INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5199{
5200 //get the running status
5201 char config_file[MAX_BUF_SIZE] = {0};
5202 char buf[16] = {0};
5203
5204 if (!output)
5205 return RETURN_ERR;
5206
5207 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5208 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5209 *output = (strncmp("0",buf,1) == 0);
5210
5211 return RETURN_OK;
5212}
5213
5214// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5215INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5216{
5217 //store the config, apply instantly
5218 char config_file[MAX_BUF_SIZE] = {0};
5219 struct params list;
5220
5221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5222 list.name = "ignore_broadcast_ssid";
5223 list.value = enable?"0":"1";
5224
5225 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5226 wifi_hostapdWrite(config_file, &list, 1);
5227 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5228 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005229 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005230 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5231
5232 return RETURN_OK;
5233}
5234
5235//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5236INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5237{
5238 //get the running status
5239 if(!output_uint)
5240 return RETURN_ERR;
5241 *output_uint=16;
5242 return RETURN_OK;
5243}
5244
5245INT wifi_setApRetryLimit(INT apIndex, UINT number)
5246{
5247 //apply instantly
5248 return RETURN_ERR;
5249}
5250
5251//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5252INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5253{
5254 if(!output)
5255 return RETURN_ERR;
5256 *output=TRUE;
5257 return RETURN_OK;
5258}
5259
5260//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5261INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5262{
5263 //get the running status from driver
5264 if(!output)
5265 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005266
5267 char config_file[MAX_BUF_SIZE] = {0};
5268 char buf[16] = {0};
5269
5270 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5271 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5272 if (strncmp("1",buf,1) == 0)
5273 *output = TRUE;
5274 else
5275 *output = FALSE;
5276
developer06a01d92022-09-07 16:32:39 +08005277 return RETURN_OK;
5278}
5279
5280//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5281INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5282{
5283 //get the running status from driver
5284 if(!output)
5285 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005286
5287 char config_file[MAX_BUF_SIZE] = {0};
5288 char buf[16] = {0};
5289
5290 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5291 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5292 if (strncmp("1",buf,1) == 0)
5293 *output = TRUE;
5294 else
5295 *output = FALSE;
5296
developer06a01d92022-09-07 16:32:39 +08005297 return RETURN_OK;
5298}
5299
5300// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5301INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5302{
5303 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005304 char config_file[MAX_BUF_SIZE] = {0};
5305 struct params list;
5306
5307 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5308 list.name = "wmm_enabled";
5309 list.value = enable?"1":"0";
5310
5311 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5312 wifi_hostapdWrite(config_file, &list, 1);
5313 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5314 wifi_reloadAp(apIndex);
5315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5316
5317 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005318}
5319
5320//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.
5321INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5322{
5323 //get the running status from driver
5324 if(!output)
5325 return RETURN_ERR;
5326 *output=TRUE;
5327 return RETURN_OK;
5328}
5329
5330// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5331INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5332{
5333 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005334 char config_file[MAX_BUF_SIZE] = {0};
5335 struct params list;
5336
5337 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5338 list.name = "uapsd_advertisement_enabled";
5339 list.value = enable?"1":"0";
5340
5341 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5342 wifi_hostapdWrite(config_file, &list, 1);
5343 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5344 wifi_reloadAp(apIndex);
5345 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5346
5347 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005348}
5349
5350// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5351INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5352{
5353 //save config and apply instantly.
5354 return RETURN_ERR;
5355}
5356
5357//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.
5358INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5359{
5360 //get the running status from driver
5361 if(!output_uint)
5362 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005363
5364 char output[16]={'\0'};
5365 char config_file[MAX_BUF_SIZE] = {0};
5366
5367 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5368 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5369 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5370 else {
5371 int device_num = atoi(output);
5372 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5373 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5374 return RETURN_ERR;
5375 }
5376 else {
5377 *output_uint = device_num;
5378 }
5379 }
5380
developer06a01d92022-09-07 16:32:39 +08005381 return RETURN_OK;
5382}
5383
5384INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5385{
5386 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005387 char str[MAX_BUF_SIZE]={'\0'};
5388 char cmd[MAX_CMD_SIZE]={'\0'};
5389 struct params params;
5390 char config_file[MAX_BUF_SIZE] = {0};
5391
5392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5393 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5394 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5395 return RETURN_ERR;
5396 }
5397 sprintf(str, "%d", number);
5398 params.name = "max_num_sta";
5399 params.value = str;
5400
5401 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5402 int ret = wifi_hostapdWrite(config_file, &params, 1);
5403 if (ret) {
5404 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5405 ,__func__, ret);
5406 }
5407
5408 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5409 if (ret) {
5410 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5411 ,__func__, ret);
5412 }
5413 wifi_reloadAp(apIndex);
5414 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5415
5416 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005417}
5418
5419//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.
5420INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5421{
5422 //get the current threshold
5423 if(!output_uint)
5424 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005425 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5426 if (*output_uint == 0)
5427 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005428 return RETURN_OK;
5429}
5430
5431INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5432{
5433 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005434 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5435 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005436 return RETURN_ERR;
5437}
5438
5439//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.
5440INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5441{
5442 if(!output_uint)
5443 return RETURN_ERR;
5444 *output_uint = 3;
5445 return RETURN_OK;
5446}
5447
5448//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5449INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5450{
5451 if(!output_uint)
5452 return RETURN_ERR;
5453 *output_uint = 3;
5454 return RETURN_OK;
5455}
5456
5457//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.
5458INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5459{
5460 if(!output_in_seconds)
5461 return RETURN_ERR;
5462 *output_in_seconds = 0;
5463 return RETURN_OK;
5464}
5465
5466//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
5467INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5468{
5469 if(!output || apIndex>=MAX_APS)
5470 return RETURN_ERR;
5471 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
5472 snprintf(output, 128, "None,WPA2-Personal");
5473 return RETURN_OK;
5474}
5475
5476//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5477INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5478{
5479 char config_file[MAX_BUF_SIZE] = {0};
5480 char buf[32] = {0};
5481 if (!output)
5482 return RETURN_ERR;
5483
5484 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5485 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5486
5487 strcpy(output,"None");//Copying "None" to output string for default case
5488 if((strcmp(buf, "3")==0))
5489 snprintf(output, 32, "WPA-WPA2-Personal");
5490 else if((strcmp(buf, "2")==0))
5491 snprintf(output, 32, "WPA2-Personal");
5492 else if((strcmp(buf, "1")==0))
5493 snprintf(output, 32, "WPA-Personal");
5494 //TODO: need to handle enterprise authmode
5495
5496 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5497 return RETURN_OK;
5498#if 0
5499 //TODO: need to revisit below implementation
5500 char securityType[32], authMode[32];
5501 int enterpriseMode=0;
5502
5503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5504 if(!output)
5505 return RETURN_ERR;
5506
5507 wifi_getApBeaconType(apIndex, securityType);
5508 strcpy(output,"None");//By default, copying "None" to output string
5509 if (strncmp(securityType,"None", strlen("None")) == 0)
5510 return RETURN_OK;
5511
5512 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5513 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5514
5515 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5516 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5517 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5518 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5519 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5520 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5522
5523 return RETURN_OK;
5524#endif
5525}
5526
5527INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
5528{
5529 char securityType[32];
5530 char authMode[32];
5531
5532 //store settings and wait for wifi up to apply
5533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5534 if(!encMode)
5535 return RETURN_ERR;
5536
5537 printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
5538 if (strcmp(encMode, "None")==0)
5539 {
5540 strcpy(securityType,"None");
5541 strcpy(authMode,"None");
5542 }
5543 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
5544 {
5545 strcpy(securityType,"WPAand11i");
5546 strcpy(authMode,"PSKAuthentication");
5547 }
5548 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
5549 {
5550 strcpy(securityType,"WPAand11i");
5551 strcpy(authMode,"EAPAuthentication");
5552 }
5553 else if (strcmp(encMode, "WPA-Personal")==0)
5554 {
5555 strcpy(securityType,"WPA");
5556 strcpy(authMode,"PSKAuthentication");
5557 }
5558 else if (strcmp(encMode, "WPA-Enterprise")==0)
5559 {
5560 strcpy(securityType,"WPA");
5561 strcpy(authMode,"EAPAuthentication");
5562 }
5563 else if (strcmp(encMode, "WPA2-Personal")==0)
5564 {
5565 strcpy(securityType,"11i");
5566 strcpy(authMode,"PSKAuthentication");
5567 }
5568 else if (strcmp(encMode, "WPA2-Enterprise")==0)
5569 {
5570 strcpy(securityType,"11i");
5571 strcpy(authMode,"EAPAuthentication");
5572 }
5573 else
5574 {
5575 strcpy(securityType,"None");
5576 strcpy(authMode,"None");
5577 }
5578 wifi_setApBeaconType(apIndex, securityType);
5579 wifi_setApBasicAuthenticationMode(apIndex, authMode);
5580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5581
5582 return RETURN_OK;
5583}
5584
5585
5586//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5587// output_string must be pre-allocated as 64 character string by caller
5588// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5589INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5590{
5591 char buf[16];
5592 char config_file[MAX_BUF_SIZE] = {0};
5593
5594 if(output_string==NULL)
5595 return RETURN_ERR;
5596
5597 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5598 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5599
5600 if(strcmp(buf,"0")==0)
5601 {
5602 printf("wpa_mode is %s ......... \n",buf);
5603 return RETURN_ERR;
5604 }
5605
5606 wifi_dbg_printf("\nFunc=%s\n",__func__);
5607 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5608 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5609 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5610
5611 return RETURN_OK;
5612}
5613
5614// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5615// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5616INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5617{
5618 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5619 struct params params={'\0'};
5620 int ret;
5621 char config_file[MAX_BUF_SIZE] = {0};
5622
5623 if(NULL == preSharedKey)
5624 return RETURN_ERR;
5625
5626 params.name = "wpa_passphrase";
5627
5628 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5629 {
5630 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5631 return RETURN_ERR;
5632 }
5633 params.value = preSharedKey;
5634 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5635 ret = wifi_hostapdWrite(config_file, &params, 1);
5636 if(!ret)
5637 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5638 return ret;
5639 //TODO: call hostapd_cli for dynamic_config_control
5640}
5641
5642//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5643// outputs the passphrase, maximum 63 characters
5644INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5645{
5646 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5647
5648 wifi_dbg_printf("\nFunc=%s\n",__func__);
5649 if (NULL == output_string)
5650 return RETURN_ERR;
5651
5652 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5653 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5654 if(strcmp(buf,"0")==0)
5655 {
5656 printf("wpa_mode is %s ......... \n",buf);
5657 return RETURN_ERR;
5658 }
5659
5660 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5661 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5662
5663 return RETURN_OK;
5664}
5665
5666// sets the passphrase enviornment variable, max 63 characters
5667INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5668{
5669 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5670 struct params params={'\0'};
5671 char config_file[MAX_BUF_SIZE] = {0};
5672 int ret;
5673
5674 if(NULL == passPhrase)
5675 return RETURN_ERR;
5676
5677 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5678 {
5679 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5680 return RETURN_ERR;
5681 }
5682 params.name = "wpa_passphrase";
5683 params.value = passPhrase;
5684 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5685 ret=wifi_hostapdWrite(config_file,&params,1);
5686 if(!ret)
5687 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5688
5689 return ret;
5690}
5691
5692//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.
5693INT wifi_setApSecurityReset(INT apIndex)
5694{
5695 //apply instantly
5696 return RETURN_ERR;
5697}
5698
5699//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).
5700INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5701{
developer8f2ddd52022-09-13 15:39:24 +08005702 char config_file[64] = {0};
5703 char buf[64] = {0};
5704 char cmd[256] = {0};
5705
5706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5707
developer06a01d92022-09-07 16:32:39 +08005708 if(!IP_output || !Port_output || !RadiusSecret_output)
5709 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005710
developer8f2ddd52022-09-13 15:39:24 +08005711 // Read the first matched config
5712 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5713 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
5714 _syscmd(cmd, buf, sizeof(buf));
5715 strncpy(IP_output, buf, 64);
5716
5717 memset(buf, 0, sizeof(buf));
5718 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
5719 _syscmd(cmd, buf, sizeof(buf));
5720 *Port_output = atoi(buf);
5721
5722 memset(buf, 0, sizeof(buf));
5723 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
5724 _syscmd(cmd, buf, sizeof(buf));
5725 strncpy(RadiusSecret_output, buf, 64);
5726
5727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005728 return RETURN_OK;
5729}
5730
5731INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
5732{
developer8f2ddd52022-09-13 15:39:24 +08005733 char config_file[64] = {0};
5734 char port_str[8] = {0};
5735 char cmd[256] = {0};
5736 char buf[128] = {0};
5737
5738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5739
5740 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5741
5742 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
5743 _syscmd(cmd, buf, sizeof(buf));
5744 memset(cmd, 0, sizeof(cmd));
5745
5746 snprintf(port_str, sizeof(port_str), "%d", port);
5747 if (strlen(buf) == 0)
5748 // Append
5749 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
5750 "auth_server_addr=%s\\n"
5751 "auth_server_port=%s\\n"
5752 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
5753 else {
5754 // Delete the three lines setting after the "# radius 1" comment
5755 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
5756 _syscmd(cmd, buf, sizeof(buf));
5757 memset(cmd, 0, sizeof(cmd));
5758 // Use "# radius 1" comment to find the location to insert the radius setting
5759 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
5760 "# radius 1\\n"
5761 "auth_server_addr=%s\\n"
5762 "auth_server_port=%s\\n"
5763 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
5764 }
5765 if(_syscmd(cmd, buf, sizeof(buf))) {
5766 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
5767 return RETURN_ERR;
5768 }
5769
5770 wifi_reloadAp(apIndex);
5771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5772 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005773}
5774
5775INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
5776{
developer8f2ddd52022-09-13 15:39:24 +08005777 char config_file[64] = {0};
5778 char buf[64] = {0};
5779 char cmd[256] = {0};
5780
5781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5782
developer06a01d92022-09-07 16:32:39 +08005783 if(!IP_output || !Port_output || !RadiusSecret_output)
5784 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08005785
5786 // Read the second matched config
5787 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5788 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
5789 _syscmd(cmd, buf, sizeof(buf));
5790 strncpy(IP_output, buf, 64);
5791
5792 memset(buf, 0, sizeof(buf));
5793 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
5794 _syscmd(cmd, buf, sizeof(buf));
5795 *Port_output = atoi(buf);
5796
5797 memset(buf, 0, sizeof(buf));
5798 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
5799 _syscmd(cmd, buf, sizeof(buf));
5800 strncpy(RadiusSecret_output, buf, 64);
5801
5802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005803 return RETURN_OK;
5804}
5805
5806INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
5807{
developer8f2ddd52022-09-13 15:39:24 +08005808 char config_file[64] = {0};
5809 char port_str[8] = {0};
5810 char cmd[256] = {0};
5811 char buf[128] = {0};
5812
5813 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5814
5815 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5816
5817 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
5818 _syscmd(cmd, buf, sizeof(buf));
5819 memset(cmd, 0, sizeof(cmd));
5820
5821 snprintf(port_str, sizeof(port_str), "%d", port);
5822 if (strlen(buf) == 0)
5823 // Append
5824 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
5825 "auth_server_addr=%s\\n"
5826 "auth_server_port=%s\\n"
5827 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
5828 else {
5829 // Delete the three lines setting after the "# radius 2" comment
5830 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
5831 _syscmd(cmd, buf, sizeof(buf));
5832 memset(cmd, 0, sizeof(cmd));
5833 // Use "# radius 2" comment to find the location to insert the radius setting
5834 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
5835 "# radius 2\\n"
5836 "auth_server_addr=%s\\n"
5837 "auth_server_port=%s\\n"
5838 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
5839 }
5840 if(_syscmd(cmd, buf, sizeof(buf))) {
5841 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
5842 return RETURN_ERR;
5843 }
5844
5845 wifi_reloadAp(apIndex);
5846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5847 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005848}
5849
5850//RadiusSettings
5851INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
5852{
5853 if(!output)
5854 return RETURN_ERR;
5855
5856 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
5857 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
5858 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
5859 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
5860 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
5861 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.
5862 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
5863 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
5864 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
5865 //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.
5866
5867 return RETURN_OK;
5868}
5869
5870INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
5871{
5872 //store the paramters, and apply instantly
5873 return RETURN_ERR;
5874}
5875
5876//Device.WiFi.AccessPoint.{i}.WPS.Enable
5877//Enables or disables WPS functionality for this access point.
5878// outputs the WPS enable state of this ap in output_bool
5879INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
5880{
5881 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
5882 if(!output_bool || !(apIndex==0 || apIndex==1))
5883 return RETURN_ERR;
5884 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
5885 _syscmd(cmd, buf, sizeof(buf));
5886 if(strstr(buf, "configured"))
5887 *output_bool=TRUE;
5888 else
5889 *output_bool=FALSE;
5890
5891 return RETURN_OK;
5892}
5893
5894//Device.WiFi.AccessPoint.{i}.WPS.Enable
5895// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
5896INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
5897{
5898 char config_file[MAX_BUF_SIZE] = {0};
5899 struct params params;
5900
5901 if(!(apIndex==0 || apIndex==1))
5902 return RETURN_ERR;
5903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5904 //store the paramters, and wait for wifi up to apply
5905 params.name = "wps_state";
5906 params.value = enable ? "2":"0";
5907
5908 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5909 wifi_hostapdWrite(config_file, &params, 1);
5910 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5911 wifi_reloadAp(apIndex);
5912
5913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5914 return RETURN_OK;
5915}
5916
5917//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
5918INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
5919{
5920 if(!output)
5921 return RETURN_ERR;
5922 snprintf(output, 128, "PushButton,PIN");
5923 return RETURN_OK;
5924}
5925
5926//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
5927//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.
5928// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
5929INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
5930{
5931 if(!output)
5932 return RETURN_ERR;
5933 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
5934
5935 return RETURN_OK;
5936}
5937
5938//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
5939// 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
5940INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
5941{
5942 //apply instantly. No setting need to be stored.
5943 char methods[MAX_BUF_SIZE], *token, *next_token;
5944 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
5945 struct params params;
5946
5947 if(!methodString || !(apIndex==0 || apIndex==1))
5948 return RETURN_ERR;
5949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5950 //store the paramters, and wait for wifi up to apply
5951
5952 snprintf(methods, sizeof(methods), "%s", methodString);
5953 for(token=methods; *token; token=next_token)
5954 {
5955 strtok_r(token, ",", &next_token);
5956 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
5957 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
5958 else if(*token=='E')
5959 {
5960 if(!strcmp(methods, "Ethernet"))
5961 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
5962 else if(!strcmp(methods, "ExternalNFCToken"))
5963 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
5964 else
5965 printf("%s: Unknown WpsConfigMethod\n", __func__);
5966 }
5967 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
5968 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
5969 else if(*token=='N' && !strcmp(token, "NFCInterface"))
5970 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
5971 else if(*token=='P' )
5972 {
5973 if(!strcmp(token, "PushButton"))
5974 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
5975 else if(!strcmp(token, "PIN"))
5976 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
5977 else
5978 printf("%s: Unknown WpsConfigMethod\n", __func__);
5979 }
5980 else
5981 printf("%s: Unknown WpsConfigMethod\n", __func__);
5982 }
5983 params.name = "config_methods";
5984 params.value = config_methods;
5985 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5986 wifi_hostapdWrite(config_file, &params, 1);
5987 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5988 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5989
5990 return RETURN_OK;
5991}
5992
5993// outputs the pin value, ulong_pin must be allocated by the caller
5994INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
5995{
5996 char buf[MAX_BUF_SIZE] = {0};
5997 char cmd[MAX_CMD_SIZE] = {0};
5998
5999 if(!output_ulong || !(apIndex==0 || apIndex==1))
6000 return RETURN_ERR;
6001 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6002 _syscmd(cmd, buf, sizeof(buf));
6003 if(strlen(buf) > 0)
6004 *output_ulong=strtoul(buf, NULL, 10);
6005
6006 return RETURN_OK;
6007}
6008
6009// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6010INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6011{
6012 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6013 char ap_pin[16] = {0};
6014 char buf[MAX_BUF_SIZE] = {0};
6015 char config_file[MAX_BUF_SIZE] = {0};
6016 ULONG prev_pin = 0;
6017 struct params params;
6018
6019 if(!(apIndex==0 || apIndex==1))
6020 return RETURN_ERR;
6021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6022 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6023 params.name = "ap_pin";
6024 params.value = ap_pin;
6025 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6026 wifi_hostapdWrite(config_file, &params, 1);
6027 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6029
6030 return RETURN_OK;
6031}
6032
6033// Output string is either Not configured or Configured, max 32 characters
6034INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6035{
6036 char cmd[MAX_CMD_SIZE];
6037 char buf[MAX_BUF_SIZE]={0};
6038
6039 if(!output_string || !(apIndex==0 || apIndex==1))
6040 return RETURN_ERR;
6041 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6042 snprintf(output_string, 32, "Not configured");
6043 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6044 _syscmd(cmd, buf, sizeof(buf));
6045
developer348e3d92022-09-13 14:48:41 +08006046 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006047 snprintf(output_string, 32, "Configured");
6048 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6049
6050 return RETURN_OK;
6051}
6052
6053// sets the WPS pin for this AP
6054INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6055{
6056 char cmd[MAX_CMD_SIZE];
6057 char buf[MAX_BUF_SIZE]={0};
6058 BOOL enable;
6059
6060 if(!(apIndex==0 || apIndex==1))
6061 return RETURN_ERR;
6062 wifi_getApEnable(apIndex, &enable);
6063 if (!enable)
6064 return RETURN_ERR;
6065 wifi_getApWpsEnable(apIndex, &enable);
6066 if (!enable)
6067 return RETURN_ERR;
6068
6069 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6070 _syscmd(cmd, buf, sizeof(buf));
6071 if((strstr(buf, "OK"))!=NULL)
6072 return RETURN_OK;
6073
6074 return RETURN_ERR;
6075}
6076
6077// This function is called when the WPS push button has been pressed for this AP
6078INT wifi_setApWpsButtonPush(INT apIndex)
6079{
6080 char cmd[MAX_CMD_SIZE];
6081 char buf[MAX_BUF_SIZE]={0};
6082 BOOL enable=FALSE;
6083
6084 if(!(apIndex==0 || apIndex==1))
6085 return RETURN_ERR;
6086 wifi_getApEnable(apIndex, &enable);
6087 if (!enable)
6088 return RETURN_ERR;
6089
6090 wifi_getApWpsEnable(apIndex, &enable);
6091 if (!enable)
6092 return RETURN_ERR;
6093
6094 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6095 _syscmd(cmd, buf, sizeof(buf));
6096
6097 if((strstr(buf, "OK"))!=NULL)
6098 return RETURN_OK;
6099 return RETURN_ERR;
6100}
6101
6102// cancels WPS mode for this AP
6103INT wifi_cancelApWPS(INT apIndex)
6104{
6105 char cmd[MAX_CMD_SIZE];
6106 char buf[MAX_BUF_SIZE]={0};
6107
6108 if(!(apIndex==0 || apIndex==1))
6109 return RETURN_ERR;
6110 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6111 _syscmd(cmd,buf, sizeof(buf));
6112
6113 if((strstr(buf, "OK"))!=NULL)
6114 return RETURN_OK;
6115 return RETURN_ERR;
6116}
6117
6118//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6119//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6120INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6121{
6122 FILE *f;
6123 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6124 char cmd[256], buf[2048];
6125 char *param , *value, *line=NULL;
6126 size_t len = 0;
6127 ssize_t nread;
6128 wifi_associated_dev_t *dev=NULL;
6129
6130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6131 *associated_dev_array = NULL;
6132 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6133 _syscmd(cmd,buf,sizeof(buf));
6134 *output_array_size = atoi(buf);
6135
6136 if (*output_array_size <= 0)
6137 return RETURN_OK;
6138
6139 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6140 *associated_dev_array = dev;
6141 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6142 _syscmd(cmd,buf,sizeof(buf));
6143 f = fopen("/tmp/connected_devices.txt", "r");
6144 if (f==NULL)
6145 {
6146 *output_array_size=0;
6147 return RETURN_ERR;
6148 }
6149 while ((nread = getline(&line, &len, f)) != -1)
6150 {
6151 param = strtok(line,"=");
6152 value = strtok(NULL,"=");
6153
6154 if( strcmp("flags",param) == 0 )
6155 {
6156 value[strlen(value)-1]='\0';
6157 if(strstr (value,"AUTHORIZED") != NULL )
6158 {
6159 dev[auth_temp].cli_AuthenticationState = 1;
6160 dev[auth_temp].cli_Active = 1;
6161 auth_temp++;
6162 read_flag=1;
6163 }
6164 }
6165 if(read_flag==1)
6166 {
6167 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6168 {
6169 value[strlen(value)-1]='\0';
6170 sscanf(value, "%x:%x:%x:%x:%x:%x",
6171 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6172 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6173 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6174 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6175 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6176 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6177 mac_temp++;
6178 read_flag=0;
6179 }
6180 }
6181 }
6182 *output_array_size = auth_temp;
6183 auth_temp=0;
6184 mac_temp=0;
6185 free(line);
6186 fclose(f);
6187 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6188 return RETURN_OK;
6189}
6190
6191#define MACADDRESS_SIZE 6
6192
6193INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6194{
6195 FILE *fp = NULL;
6196 char str[MAX_BUF_SIZE] = {0};
6197 int wificlientindex = 0 ;
6198 int count = 0;
6199 int signalstrength = 0;
6200 int arr[MACADDRESS_SIZE] = {0};
6201 unsigned char mac[MACADDRESS_SIZE] = {0};
6202 UINT wifi_count = 0;
6203 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6204 char pipeCmd[MAX_CMD_SIZE] = {0};
6205
6206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6207 *output_array_size = 0;
6208 *associated_dev_array = NULL;
6209
6210 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6211 fp = popen(pipeCmd, "r");
6212 if (fp == NULL)
6213 {
6214 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6215 return RETURN_ERR;
6216 }
6217
6218 /* Read the output a line at a time - output it. */
6219 fgets(str, sizeof(str)-1, fp);
6220 wifi_count = (unsigned int) atoi ( str );
6221 *output_array_size = wifi_count;
6222 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6223 pclose(fp);
6224
6225 if(wifi_count == 0)
6226 {
6227 return RETURN_OK;
6228 }
6229 else
6230 {
6231 wifi_associated_dev3_t* temp = NULL;
6232 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6233 if(temp == NULL)
6234 {
6235 printf("Error Statement. Insufficient memory \n");
6236 return RETURN_ERR;
6237 }
6238
6239 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6240 system(pipeCmd);
6241 memset(pipeCmd,0,sizeof(pipeCmd));
6242 if(apIndex == 0)
6243 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6244 else if(apIndex == 1)
6245 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6246 system(pipeCmd);
6247
6248 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6249 if(fp == NULL)
6250 {
6251 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6252 return RETURN_ERR;
6253 }
6254 fclose(fp);
6255
6256 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6257 fp = popen(pipeCmd, "r");
6258 if(fp)
6259 {
6260 for(count =0 ; count < wifi_count; count++)
6261 {
6262 fgets(str, MAX_BUF_SIZE, fp);
6263 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6264 {
6265 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6266 {
6267 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6268
6269 }
6270 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6271 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]);
6272 }
6273 temp[count].cli_AuthenticationState = 1; //TODO
6274 temp[count].cli_Active = 1; //TODO
6275 }
6276 pclose(fp);
6277 }
6278
6279 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6280 fp = popen(pipeCmd, "r");
6281 if(fp)
6282 {
6283 pclose(fp);
6284 }
6285 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6286 if(fp)
6287 {
6288 for(count =0 ; count < wifi_count ;count++)
6289 {
6290 fgets(str, MAX_BUF_SIZE, fp);
6291 signalstrength = atoi(str);
6292 temp[count].cli_SignalStrength = signalstrength;
6293 temp[count].cli_RSSI = signalstrength;
6294 temp[count].cli_SNR = signalstrength + 95;
6295 }
6296 pclose(fp);
6297 }
6298
6299
6300 if((apIndex == 0) || (apIndex == 4))
6301 {
6302 for(count =0 ; count < wifi_count ;count++)
6303 {
6304 strcpy(temp[count].cli_OperatingStandard,"g");
6305 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6306 }
6307
6308 //BytesSent
6309 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6310 fp = popen(pipeCmd, "r");
6311 if(fp)
6312 {
6313 pclose(fp);
6314 }
6315 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6316 if(fp)
6317 {
6318 for (count = 0; count < wifi_count; count++)
6319 {
6320 fgets(str, MAX_BUF_SIZE, fp);
6321 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6322 }
6323 pclose(fp);
6324 }
6325
6326 //BytesReceived
6327 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6328 fp = popen(pipeCmd, "r");
6329 if (fp)
6330 {
6331 pclose(fp);
6332 }
6333 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6334 if (fp)
6335 {
6336 for (count = 0; count < wifi_count; count++)
6337 {
6338 fgets(str, MAX_BUF_SIZE, fp);
6339 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6340 }
6341 pclose(fp);
6342 }
6343
6344 //PacketsSent
6345 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6346 fp = popen(pipeCmd, "r");
6347 if (fp)
6348 {
6349 pclose(fp);
6350 }
6351
6352 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6353 if (fp)
6354 {
6355 for (count = 0; count < wifi_count; count++)
6356 {
6357 fgets(str, MAX_BUF_SIZE, fp);
6358 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6359 }
6360 pclose(fp);
6361 }
6362
6363 //PacketsReceived
6364 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6365 fp = popen(pipeCmd, "r");
6366 if (fp)
6367 {
6368 pclose(fp);
6369 }
6370 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6371 if (fp)
6372 {
6373 for (count = 0; count < wifi_count; count++)
6374 {
6375 fgets(str, MAX_BUF_SIZE, fp);
6376 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6377 }
6378 pclose(fp);
6379 }
6380
6381 //ErrorsSent
6382 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6383 fp = popen(pipeCmd, "r");
6384 if (fp)
6385 {
6386 pclose(fp);
6387 }
6388 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6389 if (fp)
6390 {
6391 for (count = 0; count < wifi_count; count++)
6392 {
6393 fgets(str, MAX_BUF_SIZE, fp);
6394 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6395 }
6396 pclose(fp);
6397 }
6398
6399 //ErrorsSent
6400 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6401 fp = popen(pipeCmd, "r");
6402 if (fp)
6403 {
6404 pclose(fp);
6405 }
6406 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6407 if (fp)
6408 {
6409 for (count = 0; count < wifi_count; count++)
6410 {
6411 fgets(str, MAX_BUF_SIZE, fp);
6412 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6413 }
6414 pclose(fp);
6415 }
6416
6417 //LastDataDownlinkRate
6418 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6419 fp = popen(pipeCmd, "r");
6420 if (fp)
6421 {
6422 pclose(fp);
6423 }
6424 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
6425 if (fp)
6426 {
6427 for (count = 0; count < wifi_count; count++)
6428 {
6429 fgets(str, MAX_BUF_SIZE, fp);
6430 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
6431 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
6432 }
6433 pclose(fp);
6434 }
6435
6436 //LastDataUplinkRate
6437 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
6438 fp = popen(pipeCmd, "r");
6439 if (fp)
6440 {
6441 pclose(fp);
6442 }
6443 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
6444 if (fp)
6445 {
6446 for (count = 0; count < wifi_count; count++)
6447 {
6448 fgets(str, MAX_BUF_SIZE, fp);
6449 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
6450 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
6451 }
6452 pclose(fp);
6453 }
6454
6455 }
6456 else if ((apIndex == 1) || (apIndex == 5))
6457 {
6458 for (count = 0; count < wifi_count; count++)
6459 {
6460 strcpy(temp[count].cli_OperatingStandard, "a");
6461 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
6462 temp[count].cli_BytesSent = 0;
6463 temp[count].cli_BytesReceived = 0;
6464 temp[count].cli_LastDataUplinkRate = 0;
6465 temp[count].cli_LastDataDownlinkRate = 0;
6466 temp[count].cli_PacketsSent = 0;
6467 temp[count].cli_PacketsReceived = 0;
6468 temp[count].cli_ErrorsSent = 0;
6469 }
6470 }
6471
6472 for (count = 0; count < wifi_count; count++)
6473 {
6474 temp[count].cli_Retransmissions = 0;
6475 temp[count].cli_DataFramesSentAck = 0;
6476 temp[count].cli_DataFramesSentNoAck = 0;
6477 temp[count].cli_MinRSSI = 0;
6478 temp[count].cli_MaxRSSI = 0;
6479 strncpy(temp[count].cli_InterferenceSources, "", 64);
6480 memset(temp[count].cli_IPAddress, 0, 64);
6481 temp[count].cli_RetransCount = 0;
6482 temp[count].cli_FailedRetransCount = 0;
6483 temp[count].cli_RetryCount = 0;
6484 temp[count].cli_MultipleRetryCount = 0;
6485 }
6486 *associated_dev_array = temp;
6487 }
6488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6489 return RETURN_OK;
6490}
6491
6492int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
6493{
6494 FILE *fp = NULL;
6495 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
6496 char cmd[MAX_CMD_SIZE];
6497 int count = 0;
6498
6499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6500 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
6501 fp = popen(cmd,"r");
6502 if(fp == NULL)
6503 {
6504 printf("Failed to run command in Function %s\n",__FUNCTION__);
6505 return 0;
6506 }
6507 if(fgets(path, sizeof(path)-1, fp) != NULL)
6508 {
6509 for(count=0;path[count]!='\n';count++)
6510 status[count]=path[count];
6511 status[count]='\0';
6512 }
6513 strcpy(wifi_status,status);
6514 pclose(fp);
6515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6516 return RETURN_OK;
6517}
6518
6519/* #define HOSTAPD_STA_PARAM_ENTRIES 29
6520struct hostapd_sta_param {
6521 char key[50];
6522 char value[100];
6523}
6524
6525static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
6526 int i = 0;
6527
6528 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
6529 if (strncmp(params[i].key,key,50) == 0){
6530 return &params[i].value;
6531 }
6532 i++;
6533 }
6534 return NULL;
6535
6536} */
6537
6538static unsigned int count_occurences(const char *buf, const char *word)
6539{
6540 unsigned int n = 0;
6541 char *ptr = strstr(buf, word);
6542
6543 while (ptr++) {
6544 n++;
6545 ptr = strstr(ptr, word);
6546 }
6547
6548 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
6549 return n;
6550}
6551
6552static const char *get_line_from_str_buf(const char *buf, char *line)
6553{
6554 int i;
6555 int n = strlen(buf);
6556
6557 for (i = 0; i < n; i++) {
6558 line[i] = buf[i];
6559 if (buf[i] == '\n') {
6560 line[i] = '\0';
6561 return &buf[i + 1];
6562 }
6563 }
6564
6565 return NULL;
6566}
6567
6568INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6569{
6570 unsigned int assoc_cnt = 0;
6571 char interface_name[50] = {0};
6572 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
6573 char cmd[MAX_CMD_SIZE] = {'\0'};
6574 char line[256] = {'\0'};
6575 int i = 0;
6576 int ret = 0;
6577 const char *ptr = NULL;
6578 char *key = NULL;
6579 char *val = NULL;
6580 wifi_associated_dev3_t *temp = NULL;
6581 int rssi;
6582
6583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6584
6585 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
6586 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
6587 return RETURN_ERR;
6588 }
6589
6590 // Example filtered output of 'iw dev' command:
6591 // Station 0a:69:72:10:d2:fa (on wifi0)
6592 // signal avg:-67 [-71, -71] dBm
6593 // Station 28:c2:1f:25:5f:99 (on wifi0)
6594 // signal avg:-67 [-71, -70] dBm
6595 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
6596 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
6597 return RETURN_ERR;
6598 }
6599
6600 ret = _syscmd(cmd, buf, sizeof(buf));
6601 if (ret == RETURN_ERR) {
6602 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
6603 return RETURN_ERR;
6604 }
6605
6606 *output_array_size = count_occurences(buf, "Station");
6607 if (*output_array_size == 0) return RETURN_OK;
6608
6609 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
6610 if (temp == NULL) {
6611 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
6612 return RETURN_ERR;
6613 }
6614 *associated_dev_array = temp;
6615
6616 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
6617 ptr = get_line_from_str_buf(buf, line);
6618 i = -1;
6619 while (ptr) {
6620 if (strstr(line, "Station")) {
6621 i++;
6622 key = strtok(line, " ");
6623 val = strtok(NULL, " ");
6624 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
6625 &temp[i].cli_MACAddress[0],
6626 &temp[i].cli_MACAddress[1],
6627 &temp[i].cli_MACAddress[2],
6628 &temp[i].cli_MACAddress[3],
6629 &temp[i].cli_MACAddress[4],
6630 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
6631 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
6632 free(*associated_dev_array);
6633 return RETURN_ERR;
6634 }
6635 }
6636 else if (i < 0) {
6637 ptr = get_line_from_str_buf(ptr, line);
6638 continue; // We didn't detect 'station' entry yet
6639 }
6640 else if (strstr(line, "signal avg")) {
6641 key = strtok(line, ":");
6642 val = strtok(NULL, " ");
6643 if (sscanf(val, "%d", &rssi) <= 0 ) {
6644 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
6645 free(*associated_dev_array);
6646 return RETURN_ERR;
6647 }
6648 temp[i].cli_RSSI = rssi;
6649 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
6650 }
6651 // Here other fields can be parsed if added to filter of 'iw dev' command
6652
6653 ptr = get_line_from_str_buf(ptr, line);
6654 };
6655
6656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6657
6658 return RETURN_OK;
6659}
6660
6661#if 0
6662//To-do
6663INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6664{
6665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6666
6667 //Using different approach to get required WiFi Parameters from system available commands
6668#if 0
6669 FILE *f;
6670 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6671 char cmd[256], buf[2048];
6672 char *param , *value, *line=NULL;
6673 size_t len = 0;
6674 ssize_t nread;
6675 wifi_associated_dev3_t *dev=NULL;
6676 *associated_dev_array = NULL;
6677 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6678 _syscmd(cmd,buf,sizeof(buf));
6679 *output_array_size = atoi(buf);
6680
6681 if (*output_array_size <= 0)
6682 return RETURN_OK;
6683
6684 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
6685 *associated_dev_array = dev;
6686 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
6687 _syscmd(cmd,buf,sizeof(buf));
6688 f = fopen("/tmp/connected_devices.txt", "r");
6689 if (f==NULL)
6690 {
6691 *output_array_size=0;
6692 return RETURN_ERR;
6693 }
6694 while ((nread = getline(&line, &len, f)) != -1)
6695 {
6696 param = strtok(line,"=");
6697 value = strtok(NULL,"=");
6698
6699 if( strcmp("flags",param) == 0 )
6700 {
6701 value[strlen(value)-1]='\0';
6702 if(strstr (value,"AUTHORIZED") != NULL )
6703 {
6704 dev[auth_temp].cli_AuthenticationState = 1;
6705 dev[auth_temp].cli_Active = 1;
6706 auth_temp++;
6707 read_flag=1;
6708 }
6709 }
6710 if(read_flag==1)
6711 {
6712 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6713 {
6714 value[strlen(value)-1]='\0';
6715 sscanf(value, "%x:%x:%x:%x:%x:%x",
6716 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6717 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6718 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6719 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6720 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6721 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6722
6723 }
6724 else if( strcmp("rx_packets",param) == 0 )
6725 {
6726 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
6727 }
6728
6729 else if( strcmp("tx_packets",param) == 0 )
6730 {
6731 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
6732 }
6733
6734 else if( strcmp("rx_bytes",param) == 0 )
6735 {
6736 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
6737 }
6738
6739 else if( strcmp("tx_bytes",param) == 0 )
6740 {
6741 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
6742 mac_temp++;
6743 read_flag=0;
6744 }
6745 }
6746 }
6747
6748 *output_array_size = auth_temp;
6749 auth_temp=0;
6750 mac_temp=0;
6751 free(line);
6752 fclose(f);
6753#endif
6754 char interface_name[MAX_BUF_SIZE] = {0};
6755 char wifi_status[MAX_BUF_SIZE] = {0};
6756 char hostapdconf[MAX_BUF_SIZE] = {0};
6757
6758 wifi_associated_dev3_t *dev_array = NULL;
6759 ULONG wifi_count = 0;
6760
6761 *associated_dev_array = NULL;
6762 *output_array_size = 0;
6763
6764 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
6765 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
6766 {
6767 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
6768
6769 GetInterfaceName(interface_name, hostapdconf);
6770
6771 if(strlen(interface_name) > 1)
6772 {
6773 wifihal_interfacestatus(wifi_status,interface_name);
6774 if(strcmp(wifi_status,"RUNNING") == 0)
6775 {
6776 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
6777
6778 *associated_dev_array = dev_array;
6779 *output_array_size = wifi_count;
6780 }
6781 else
6782 {
6783 *associated_dev_array = NULL;
6784 }
6785 }
6786 }
6787
6788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6789 return RETURN_OK;
6790}
6791#endif
6792
6793/* getIPAddress function */
6794/**
6795* @description Returning IpAddress of the Matched String
6796*
6797* @param
6798* @str Having MacAddress
6799* @ipaddr Having ipaddr
6800* @return The status of the operation
6801* @retval RETURN_OK if successful
6802* @retval RETURN_ERR if any error is detected
6803*
6804*/
6805
6806INT getIPAddress(char *str,char *ipaddr)
6807{
6808 FILE *fp = NULL;
6809 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
6810 int LeaseTime = 0,ret = 0;
6811 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
6812 {
6813 return RETURN_ERR;
6814 }
6815
6816 while ( fgets(buf, sizeof(buf), fp)!= NULL )
6817 {
6818 /*
6819 Sample:sss
6820 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
6821 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
6822 */
6823 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
6824 &(LeaseTime),
6825 phyAddr,
6826 ipAddr,
6827 hostName
6828 );
6829 if(ret != 4)
6830 continue;
6831 if(strcmp(str,phyAddr) == 0)
6832 strcpy(ipaddr,ipAddr);
6833 }
6834 return RETURN_OK;
6835}
6836
6837/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
6838/**
6839* @description Returning Inactive wireless connected clients informations
6840*
6841* @param
6842* @filename Holding private_wifi 2g/5g content files
6843* @associated_dev_array Having inactiv wireless clients informations
6844* @output_array_size Returning Inactive wireless counts
6845* @return The status of the operation
6846* @retval RETURN_OK if successful
6847* @retval RETURN_ERR if any error is detected
6848*
6849*/
6850
6851INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6852{
6853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6854 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
6855 FILE *fp = NULL;
6856 int arr[MACADDRESS_SIZE] = {0};
6857 unsigned char mac[MACADDRESS_SIZE] = {0};
6858 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
6859 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
6860 fp = popen(buf,"r");
6861 if(fp == NULL)
6862 return RETURN_ERR;
6863 else
6864 {
6865 fgets(path,sizeof(path),fp);
6866 maccount = atoi(path);
6867 }
6868 pclose(fp);
6869 *output_array_size = maccount;
6870 wifi_associated_dev3_t* temp = NULL;
6871 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
6872 *associated_dev_array = temp;
6873 if(temp == NULL)
6874 {
6875 printf("Error Statement. Insufficient memory \n");
6876 return RETURN_ERR;
6877 }
6878 memset(buf,0,sizeof(buf));
6879 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
6880 fp = popen(buf,"r");
6881 for(count = 0; count < maccount ; count++)
6882 {
6883 fgets(path,sizeof(path),fp);
6884 for(i = 0; path[i]!='\n';i++)
6885 str[i]=path[i];
6886 str[i]='\0';
6887 getIPAddress(str,ipaddr);
6888 memset(buf,0,sizeof(buf));
6889 if(strlen(ipaddr) > 0)
6890 {
6891 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
6892 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
6893 {
6894 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6895 {
6896 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6897 {
6898 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6899
6900 }
6901 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6902 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]);
6903 }
6904 temp[count].cli_AuthenticationState = 0; //TODO
6905 temp[count].cli_Active = 0; //TODO
6906 temp[count].cli_SignalStrength = 0;
6907 }
6908 else //Active wireless clients info
6909 {
6910 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6911 {
6912 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6913 {
6914 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6915
6916 }
6917 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6918 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]);
6919 }
6920 temp[count].cli_Active = 1;
6921 }
6922 }
6923 memset(ipaddr,0,sizeof(ipaddr));
6924 }
6925 pclose(fp);
6926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6927 return RETURN_OK;
6928}
6929//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
6930//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
6931//To get Band Steering Capability
6932INT wifi_getBandSteeringCapability(BOOL *support)
6933{
6934 *support = FALSE;
6935 return RETURN_OK;
6936}
6937
6938
6939//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
6940//To get Band Steering enable status
6941INT wifi_getBandSteeringEnable(BOOL *enable)
6942{
6943 *enable = FALSE;
6944 return RETURN_OK;
6945}
6946
6947//To turn on/off Band steering
6948INT wifi_setBandSteeringEnable(BOOL enable)
6949{
6950 return RETURN_OK;
6951}
6952
6953//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
6954//To get Band Steering AP group
6955INT wifi_getBandSteeringApGroup(char *output_ApGroup)
6956{
6957 if (NULL == output_ApGroup)
6958 return RETURN_ERR;
6959
6960 strcpy(output_ApGroup, "1,2");
6961 return RETURN_OK;
6962}
6963
6964//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
6965//to set and read the band steering BandUtilizationThreshold parameters
6966INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
6967{
6968 return RETURN_ERR;
6969}
6970
6971INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
6972{
6973 return RETURN_ERR;
6974}
6975
6976//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
6977//to set and read the band steering RSSIThreshold parameters
6978INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
6979{
6980 return RETURN_ERR;
6981}
6982
6983INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
6984{
6985 return RETURN_ERR;
6986}
6987
6988
6989//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
6990//to set and read the band steering physical modulation rate threshold parameters
6991INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
6992{
6993 //If chip is not support, return -1
6994 return RETURN_ERR;
6995}
6996
6997INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
6998{
6999 //If chip is not support, return -1
7000 return RETURN_ERR;
7001}
7002
7003//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7004//to set and read the inactivity time (in seconds) for steering under overload condition
7005INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7006{
7007 return RETURN_ERR;
7008}
7009
7010INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7011{
7012 return RETURN_ERR;
7013}
7014
7015//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7016//to set and read the inactivity time (in seconds) for steering under Idle condition
7017INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7018{
7019 return RETURN_ERR;
7020}
7021
7022INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7023{
7024 return RETURN_ERR;
7025}
7026
7027//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7028//pClientMAC[64]
7029//pSourceSSIDIndex[64]
7030//pDestSSIDIndex[64]
7031//pSteeringReason[256]
7032INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7033{
7034 //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
7035 *pSteeringTime=time(NULL);
7036 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7037 return RETURN_OK;
7038}
7039
7040INT wifi_ifConfigDown(INT apIndex)
7041{
7042 INT status = RETURN_OK;
7043 char cmd[64];
7044
7045 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7046 printf("%s: %s\n", __func__, cmd);
7047 system(cmd);
7048
7049 return status;
7050}
7051
7052INT wifi_ifConfigUp(INT apIndex)
7053{
7054 char cmd[128];
7055 char buf[1024];
7056
7057 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7058 _syscmd(cmd, buf, sizeof(buf));
7059 return 0;
7060}
7061
7062//>> Deprecated. Replace with wifi_applyRadioSettings
7063INT wifi_pushBridgeInfo(INT apIndex)
7064{
7065 char ip[32];
7066 char subnet[32];
7067 char bridge[32];
7068 int vlanId;
7069 char cmd[128];
7070 char buf[1024];
7071
7072 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7073 wifi_getApVlanID(apIndex,&vlanId);
7074
7075 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7076 _syscmd(cmd,buf, sizeof(buf));
7077
7078 return 0;
7079}
7080
7081INT wifi_pushChannel(INT radioIndex, UINT channel)
7082{
7083 char cmd[128];
7084 char buf[1024];
7085 int apIndex;
7086
7087 apIndex=(radioIndex==0)?0:1;
7088 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7089 _syscmd(cmd,buf, sizeof(buf));
7090
7091 return 0;
7092}
7093
7094INT wifi_pushChannelMode(INT radioIndex)
7095{
7096 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7097 return RETURN_ERR;
7098}
7099
7100INT wifi_pushDefaultValues(INT radioIndex)
7101{
7102 //Apply Comcast specified default radio settings instantly
7103 //AMPDU=1
7104 //AMPDUFrames=32
7105 //AMPDULim=50000
7106 //txqueuelen=1000
7107
7108 return RETURN_ERR;
7109}
7110
7111INT wifi_pushTxChainMask(INT radioIndex)
7112{
7113 //Apply default TxChainMask instantly
7114 return RETURN_ERR;
7115}
7116
7117INT wifi_pushRxChainMask(INT radioIndex)
7118{
7119 //Apply default RxChainMask instantly
7120 return RETURN_ERR;
7121}
7122
7123INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7124{
7125 INT status;
7126
7127 status = wifi_setSSIDName(apIndex,ssid);
7128 wifi_setApEnable(apIndex,FALSE);
7129 wifi_setApEnable(apIndex,TRUE);
7130
7131 return status;
7132}
7133
7134INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7135{
7136 //Apply default Ssid Advertisement instantly
7137 return RETURN_ERR;
7138}
7139
7140INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7141{
7142 INT status = RETURN_ERR;
7143 *output = 0;
7144 return RETURN_ERR;
7145}
7146
7147INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7148{
7149 return RETURN_OK;
7150}
7151
7152INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7153{
7154 return RETURN_OK;
7155}
7156
7157//To-do
7158INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7159{
developereb199ae2022-09-13 14:04:27 +08007160 char output[16]={'\0'};
7161 char config_file[MAX_BUF_SIZE] = {0};
7162
7163 if (!output_string)
7164 return RETURN_ERR;
7165
7166 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7167 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7168
7169 if (strlen(output) == 0)
7170 snprintf(output_string, 64, "Disabled");
7171 else if (strncmp(output, "0", 1) == 0)
7172 snprintf(output_string, 64, "Disabled");
7173 else if (strncmp(output, "1", 1) == 0)
7174 snprintf(output_string, 64, "Optional");
7175 else if (strncmp(output, "2", 1) == 0)
7176 snprintf(output_string, 64, "Required");
7177 else {
7178 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7179 return RETURN_ERR;
7180 }
7181
7182 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007183 return RETURN_OK;
7184}
7185INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7186{
developereb199ae2022-09-13 14:04:27 +08007187 char str[MAX_BUF_SIZE]={'\0'};
7188 char cmd[MAX_CMD_SIZE]={'\0'};
7189 struct params params;
7190 char config_file[MAX_BUF_SIZE] = {0};
7191
7192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7193 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7194 return RETURN_ERR;
7195
7196 params.name = "ieee80211w";
7197 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7198 params.value = "0";
7199 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7200 params.value = "1";
7201 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7202 params.value = "2";
7203 else{
7204 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7205 return RETURN_ERR;
7206 }
7207 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7208 wifi_hostapdWrite(config_file, &params, 1);
7209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007210 return RETURN_OK;
7211}
7212INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7213{
7214 char output[16]={'\0'};
7215 char config_file[MAX_BUF_SIZE] = {0};
7216
7217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7218 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7219 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7220
7221 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7222 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7223
7224 return RETURN_OK;
7225}
7226
7227INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7228{
7229 return RETURN_OK;
7230}
7231
7232INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7233{
7234 return RETURN_OK;
7235}
7236
7237INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7238{
7239 return RETURN_OK;
7240}
7241
7242INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7243{
7244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7245 char config_file[MAX_BUF_SIZE] = {0};
7246
7247 if (NULL == output)
7248 return RETURN_ERR;
7249 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7250 wifi_hostapdRead(config_file,"hw_mode",output,64);
7251
7252 if(strcmp(output,"b")==0)
7253 sprintf(output, "%s", "1,2,5.5,11");
7254 else if (strcmp(output,"a")==0)
7255 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7256 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7257 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7258
7259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7260 return RETURN_OK;
7261}
7262
7263INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7264{
7265 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7266 char *temp;
7267 char temp_output[128];
7268 char temp_TransmitRates[128];
7269 char config_file[MAX_BUF_SIZE] = {0};
7270
7271 if (NULL == output)
7272 return RETURN_ERR;
7273
7274 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7275 wifi_hostapdRead(config_file,"supported_rates",output,64);
7276
7277 strcpy(temp_TransmitRates,output);
7278 strcpy(temp_output,"");
7279 temp = strtok(temp_TransmitRates," ");
7280 while(temp!=NULL)
7281 {
7282 temp[strlen(temp)-1]=0;
7283 if((temp[0]=='5') && (temp[1]=='\0'))
7284 {
7285 temp="5.5";
7286 }
7287 strcat(temp_output,temp);
7288 temp = strtok(NULL," ");
7289 if(temp!=NULL)
7290 {
7291 strcat(temp_output,",");
7292 }
7293 }
7294 strcpy(output,temp_output);
7295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7296
7297 return RETURN_OK;
7298}
7299
7300INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7301{
7302 return RETURN_OK;
7303}
7304
7305
7306INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7307{
7308 int i=0;
7309 char *temp;
7310 char temp1[128];
7311 char temp_output[128];
7312 char temp_TransmitRates[128];
7313 struct params params={'\0'};
7314 char config_file[MAX_BUF_SIZE] = {0};
7315
7316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7317 if(NULL == output)
7318 return RETURN_ERR;
7319
7320 strcpy(temp_TransmitRates,output);
7321
7322 for(i=0;i<strlen(temp_TransmitRates);i++)
7323 {
7324 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7325 {
7326 continue;
7327 }
7328 else
7329 {
7330 return RETURN_ERR;
7331 }
7332 }
7333 strcpy(temp_output,"");
7334 temp = strtok(temp_TransmitRates," ");
7335 while(temp!=NULL)
7336 {
7337 strcpy(temp1,temp);
7338 if(wlanIndex==1)
7339 {
7340 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7341 {
7342 return RETURN_ERR;
7343 }
7344 }
7345
7346 if(strcmp(temp,"5.5")==0)
7347 {
7348 strcpy(temp1,"55");
7349 }
7350 else
7351 {
7352 strcat(temp1,"0");
7353 }
7354 strcat(temp_output,temp1);
7355 temp = strtok(NULL," ");
7356 if(temp!=NULL)
7357 {
7358 strcat(temp_output," ");
7359 }
7360 }
7361 strcpy(output,temp_output);
7362
7363
7364 params.name = "supported_rates";
7365 params.value = output;
7366
7367 wifi_dbg_printf("\n%s:",__func__);
7368 wifi_dbg_printf("params.value=%s\n",params.value);
7369 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7370 wifi_hostapdWrite(config_file,&params,1);
7371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7372
7373 return RETURN_OK;
7374}
7375
7376
7377static char *sncopy(char *dst, int dst_sz, const char *src)
7378{
7379 if (src && dst && dst_sz > 0) {
7380 strncpy(dst, src, dst_sz);
7381 dst[dst_sz - 1] = '\0';
7382 }
7383 return dst;
7384}
7385
7386static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7387{
7388 if (0 == strcmp(ht_mode, "HT40") ||
7389 0 == strcmp(ht_mode, "HT80") ||
7390 0 == strcmp(ht_mode, "HT160")) {
7391 switch (channel) {
7392 case 1 ... 7:
7393 case 36:
7394 case 44:
7395 case 52:
7396 case 60:
7397 case 100:
7398 case 108:
7399 case 116:
7400 case 124:
7401 case 132:
7402 case 140:
7403 case 149:
7404 case 157:
7405 return 1;
7406 case 8 ... 13:
7407 case 40:
7408 case 48:
7409 case 56:
7410 case 64:
7411 case 104:
7412 case 112:
7413 case 120:
7414 case 128:
7415 case 136:
7416 case 144:
7417 case 153:
7418 case 161:
7419 return -1;
7420 default:
7421 return -EINVAL;
7422 }
7423 }
7424
7425 return -EINVAL;
7426}
7427
7428static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
7429{
7430 if (NULL == hw_mode) return;
7431
7432 if (0 == strcmp(hw_mode, "ac"))
7433 sncopy(bw_mode, bw_mode_len, "ht vht");
7434
7435 if (0 == strcmp(hw_mode, "n"))
7436 sncopy(bw_mode, bw_mode_len, "ht");
7437
7438 return;
7439}
7440
7441static int util_chan_to_freq(int chan)
7442{
7443 if (chan == 14)
7444 return 2484;
7445 else if (chan < 14)
7446 return 2407 + chan * 5;
7447 else if (chan >= 182 && chan <= 196)
7448 return 4000 + chan * 5;
7449 else
7450 return 5000 + chan * 5;
7451 return 0;
7452}
7453
7454const int *util_unii_5g_chan2list(int chan, int width)
7455{
7456 static const int lists[] = {
7457 // <width>, <chan1>, <chan2>..., 0,
7458 20, 36, 0,
7459 20, 40, 0,
7460 20, 44, 0,
7461 20, 48, 0,
7462 20, 52, 0,
7463 20, 56, 0,
7464 20, 60, 0,
7465 20, 64, 0,
7466 20, 100, 0,
7467 20, 104, 0,
7468 20, 108, 0,
7469 20, 112, 0,
7470 20, 116, 0,
7471 20, 120, 0,
7472 20, 124, 0,
7473 20, 128, 0,
7474 20, 132, 0,
7475 20, 136, 0,
7476 20, 140, 0,
7477 20, 144, 0,
7478 20, 149, 0,
7479 20, 153, 0,
7480 20, 157, 0,
7481 20, 161, 0,
7482 20, 165, 0,
7483 40, 36, 40, 0,
7484 40, 44, 48, 0,
7485 40, 52, 56, 0,
7486 40, 60, 64, 0,
7487 40, 100, 104, 0,
7488 40, 108, 112, 0,
7489 40, 116, 120, 0,
7490 40, 124, 128, 0,
7491 40, 132, 136, 0,
7492 40, 140, 144, 0,
7493 40, 149, 153, 0,
7494 40, 157, 161, 0,
7495 80, 36, 40, 44, 48, 0,
7496 80, 52, 56, 60, 64, 0,
7497 80, 100, 104, 108, 112, 0,
7498 80, 116, 120, 124, 128, 0,
7499 80, 132, 136, 140, 144, 0,
7500 80, 149, 153, 157, 161, 0,
7501 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
7502 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
7503 -1 // final delimiter
7504 };
7505 const int *start;
7506 const int *p;
7507
7508 for (p = lists; *p != -1; p++) {
7509 if (*p == width) {
7510 for (start = ++p; *p != 0; p++) {
7511 if (*p == chan)
7512 return start;
7513 }
7514 }
7515 // move to the end of channel list of given width
7516 while (*p != 0) {
7517 p++;
7518 }
7519 }
7520
7521 return NULL;
7522}
7523
7524static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
7525{
7526 if (NULL == ht_mode)
7527 return 0;
7528
7529 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
7530 const int *chans = util_unii_5g_chan2list(channel, width);
7531 int sum = 0;
7532 int cnt = 0;
7533
7534 if (NULL == chans)
7535 return 0;
7536
7537 while (*chans) {
7538 sum += *chans;
7539 cnt++;
7540 chans++;
7541 }
7542 return sum / cnt;
7543}
7544
7545static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
7546{
7547 BOOL onlyG, onlyN, onlyA;
7548 CHAR tmp[64];
7549 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
7550 if (ret == RETURN_OK) {
7551 sncopy(hw_mode, hw_mode_size, tmp);
7552 }
7553 return ret;
7554}
7555
7556INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
7557{
7558 // Sample commands:
7559 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
7560 // hostapd_cli -i wifi0 chan_switch 30 2437
7561 char cmd[MAX_CMD_SIZE] = {0};
7562 char buf[MAX_BUF_SIZE] = {0};
7563 int freq = 0, ret = 0;
7564 char center_freq1_str[32] = ""; // center_freq1=%d
7565 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
7566 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
7567 char hw_mode[16] = ""; // n|ac
7568 char bw_mode[16] = ""; // ht|ht vht
7569 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
7570 int sec_chan_offset;
7571 int width;
7572
7573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7574
7575 freq = util_chan_to_freq(channel);
7576
7577 // Get radio mode HT20|HT40|HT80 etc.
7578 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
7579 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
7580 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
7581 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
7582 if (sec_chan_offset != -EINVAL)
7583 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
7584
7585
7586 // Provide bandwith if specified
7587 if (channel_width_MHz > 20) {
7588 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
7589 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
7590 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
7591
7592 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
7593 }
7594
7595 int center_chan = 0;
7596 if (channel_width_MHz > 20) {
7597 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
7598 if (center_chan > 0) {
7599 int center_freq1 = util_chan_to_freq(center_chan);
7600 if (center_freq1)
7601 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
7602 }
7603 }
7604
7605 {
7606 // Only the first AP, other are hanging on the same radio
7607 int apIndex = radioIndex;
7608 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
7609 AP_PREFIX, apIndex, csa_beacon_count, freq,
7610 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
7611 wifi_dbg_printf("execute: '%s'\n", cmd);
7612 ret = _syscmd(cmd, buf, sizeof(buf));
7613 }
7614
7615 wifi_setRadioChannel(radioIndex, channel);
7616
7617 char *ext_str = "None";
7618 if (sec_chan_offset == 1) ext_str = "Above";
7619 else if (sec_chan_offset == -1) ext_str = "Below";
7620 wifi_setRadioExtChannel(radioIndex, ext_str);
7621
7622 wifi_setRadioCenterChannel(radioIndex, center_chan);
7623
7624 char mhz_str[16];
7625 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
7626 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
7627
7628 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7629
7630 return RETURN_OK;
7631}
7632
7633INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
7634{
7635 char cmd[1024] = {0};
7636 char buf[1024] = {0};
7637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7638 wifi_neighbor_ap2_t *scan_array = NULL;
7639 int scan_count=0;
7640 int i =0;
7641 int freq=0;
7642 size_t len=0;
7643 FILE *f = NULL;
7644 ssize_t read = 0;
7645 char *line =NULL;
7646 char radio_ifname[64];
7647 char secondary_chan[64];
7648 int vht_channel_width = 0;
7649
7650 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
7651 return RETURN_ERR;
7652
7653 /* sched_start is not supported on open source ath9k ath10k firmware
7654 * Using active scan as a workaround */
7655 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
7656 if((f = popen(cmd, "r")) == NULL) {
7657 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7658 return RETURN_ERR;
7659 }
7660 read = getline(&line, &len, f);
7661 while (read != -1) {
7662 if(strncmp(line,"BSS",3) == 0) {
7663 i = scan_count;
7664 scan_count++;
7665 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
7666 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
7667 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
7668
7669 read = getline(&line, &len, f);
7670 sscanf(line," freq: %d", &freq);
7671 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
7672
7673 read = getline(&line, &len, f);
7674 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
7675
7676 read = getline(&line, &len, f);
7677 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
7678 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);
7679 read = getline(&line, &len, f);
7680 if(strncmp(line,"BSS",3)==0) {
7681 // No HT and no VHT => 20Mhz
7682 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
7683 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7684 continue;
7685 }
7686 if(strncmp(line," HT operation:",14)!= 0) {
7687 wifi_dbg_printf("HT output parsing error (%s)\n", line);
7688 goto output_error;
7689 }
7690
7691 read = getline(&line, &len, f);
7692 sscanf(line," * secondary channel offset: %s", &secondary_chan);
7693
7694 if(!strcmp(secondary_chan, "no")) {
7695 //20Mhz
7696 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
7697 }
7698
7699 if(!strcmp(secondary_chan, "above")) {
7700 //40Mhz +
7701 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
7702 }
7703
7704 if(!strcmp(secondary_chan, "below")) {
7705 //40Mhz -
7706 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
7707 }
7708
7709
7710 read = getline(&line, &len, f);
7711 if(strncmp(line," VHT operation:",15) !=0) {
7712 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7713 // No VHT
7714 continue;
7715 }
7716 read = getline(&line, &len, f);
7717 sscanf(line," * channel width: %d", &vht_channel_width);
7718 if(vht_channel_width == 1) {
7719 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
7720 } else {
7721 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
7722 }
7723
7724 }
7725 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
7726 read = getline(&line, &len, f);
7727 }
7728 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
7729 *output_array_size = scan_count;
7730 *neighbor_ap_array = scan_array;
7731 free(line);
7732 pclose(f);
7733 return RETURN_OK;
7734
7735output_error:
7736 pclose(f);
7737 free(line);
7738 free(scan_array);
7739 return RETURN_ERR;
7740}
7741INT wifi_getApAssociatedDeviceStats(
7742 INT apIndex,
7743 mac_address_t *clientMacAddress,
7744 wifi_associated_dev_stats_t *associated_dev_stats,
7745 u64 *handle)
7746{
7747 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
7748 char interface_name[50] = {0};
7749 char cmd[1024] = {0};
7750 char mac_str[18] = {0};
7751 char *key = NULL;
7752 char *val = NULL;
7753 FILE *f = NULL;
7754 char *line = NULL;
7755 size_t len = 0;
7756 ssize_t read = 0;
7757
7758 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7759 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7760 return RETURN_ERR;
7761 }
7762
7763 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
7764 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
7765 if((f = popen(cmd, "r")) == NULL) {
7766 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7767 return RETURN_ERR;
7768 }
7769
7770 while ((read = getline(&line, &len, f)) != -1) {
7771 key = strtok(line,":");
7772 val = strtok(NULL,":");
7773
7774 if(!strncmp(key,"rx bytes",8))
7775 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
7776 if(!strncmp(key,"tx bytes",8))
7777 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
7778 if(!strncmp(key,"rx packets",10))
7779 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
7780 if(!strncmp(key,"tx packets",10))
7781 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
7782 if(!strncmp(key,"tx retries",10))
7783 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
7784 if(!strncmp(key,"tx failed",9))
7785 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
7786 if(!strncmp(key,"rx drop misc",13))
7787 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
7788 if(!strncmp(key,"rx bitrate",10)) {
7789 val = strtok(val, " ");
7790 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
7791 }
7792 if(!strncmp(key,"tx bitrate",10)) {
7793 val = strtok(val, " ");
7794 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
7795 }
7796 }
7797 free(line);
7798 pclose(f);
7799 return RETURN_OK;
7800}
7801
7802INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
7803{
7804 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
7805
7806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7807 if (NULL == output_string)
7808 return RETURN_ERR;
7809
7810 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
7811 _syscmd(cmd, buf, sizeof(buf));
7812
7813 //size of SSID name restricted to value less than 32 bytes
7814 snprintf(output_string, 32, "%s", buf);
7815 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7816
7817 return RETURN_OK;
7818}
7819
7820INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
7821{
7822 //char cmd[MAX_CMD_SIZE] = {0};
7823 char config_file[MAX_BUF_SIZE] = {0};
7824 char buf[32] = {0};
7825
7826 if (!output_filterMode)
7827 return RETURN_ERR;
7828
7829 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
7830 //_syscmd(cmd, buf, sizeof(buf));
7831 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7832 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08007833 if(strlen(buf) == 0) {
7834 *output_filterMode = 0;
7835 }
7836 else {
7837 int macaddr_acl_mode = strtol(buf, NULL, 10);
7838 if (macaddr_acl_mode == 1) {
7839 *output_filterMode = 1;
7840 } else if (macaddr_acl_mode == 0) {
7841 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
7842 if (strlen(buf) == 0) {
7843 *output_filterMode = 0;
7844 } else {
7845 *output_filterMode = 2;
7846 }
7847 } else {
7848 return RETURN_ERR;
7849 }
7850 }
developer06a01d92022-09-07 16:32:39 +08007851
7852 return RETURN_OK;
7853}
7854
7855INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
7856{
7857 FILE *fp = NULL;
7858 char str[MAX_BUF_SIZE] = {0};
7859 int wificlientindex = 0 ;
7860 int count = 0;
7861 int signalstrength = 0;
7862 int arr[MACADDRESS_SIZE] = {0};
7863 unsigned char mac[MACADDRESS_SIZE] = {0};
7864 UINT wifi_count = 0;
7865 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7866 char pipeCmd[MAX_CMD_SIZE] = {0};
7867
7868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7869 *output_array_size = 0;
7870 *associated_dev_array = NULL;
7871 char interface_name[50] = {0};
7872
7873 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7874 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7875 return RETURN_ERR;
7876 }
7877
7878 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7879 fp = popen(pipeCmd, "r");
7880 if (fp == NULL)
7881 {
7882 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7883 return RETURN_ERR;
7884 }
7885
7886 /* Read the output a line at a time - output it. */
7887 fgets(str, sizeof(str)-1, fp);
7888 wifi_count = (unsigned int) atoi ( str );
7889 *output_array_size = wifi_count;
7890 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7891 pclose(fp);
7892
7893 if(wifi_count == 0)
7894 {
7895 return RETURN_OK;
7896 }
7897 else
7898 {
7899 wifi_associated_dev2_t* temp = NULL;
7900 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
7901 *associated_dev_array = temp;
7902 if(temp == NULL)
7903 {
7904 printf("Error Statement. Insufficient memory \n");
7905 return RETURN_ERR;
7906 }
7907
7908 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7909 system(pipeCmd);
7910
7911 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7912 if(fp == NULL)
7913 {
7914 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7915 return RETURN_ERR;
7916 }
7917 fclose(fp);
7918
7919 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
7920 fp = popen(pipeCmd, "r");
7921 if(fp)
7922 {
7923 for(count =0 ; count < wifi_count; count++)
7924 {
7925 fgets(str, MAX_BUF_SIZE, fp);
7926 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7927 {
7928 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7929 {
7930 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7931
7932 }
7933 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7934 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]);
7935 }
7936 temp[count].cli_AuthenticationState = 1; //TODO
7937 temp[count].cli_Active = 1; //TODO
7938 }
7939 pclose(fp);
7940 }
7941
7942 //Updating RSSI per client
7943 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
7944 fp = popen(pipeCmd, "r");
7945 if(fp)
7946 {
7947 pclose(fp);
7948 }
7949 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7950 if(fp)
7951 {
7952 for(count =0 ; count < wifi_count ;count++)
7953 {
7954 fgets(str, MAX_BUF_SIZE, fp);
7955 signalstrength = atoi(str);
7956 temp[count].cli_RSSI = signalstrength;
7957 }
7958 pclose(fp);
7959 }
7960
7961
7962 //LastDataDownlinkRate
7963 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7964 fp = popen(pipeCmd, "r");
7965 if (fp)
7966 {
7967 pclose(fp);
7968 }
7969 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7970 if (fp)
7971 {
7972 for (count = 0; count < wifi_count; count++)
7973 {
7974 fgets(str, MAX_BUF_SIZE, fp);
7975 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7976 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7977 }
7978 pclose(fp);
7979 }
7980
7981 //LastDataUplinkRate
7982 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7983 fp = popen(pipeCmd, "r");
7984 if (fp)
7985 {
7986 pclose(fp);
7987 }
7988 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7989 if (fp)
7990 {
7991 for (count = 0; count < wifi_count; count++)
7992 {
7993 fgets(str, MAX_BUF_SIZE, fp);
7994 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7995 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7996 }
7997 pclose(fp);
7998 }
7999 }
8000 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8001 return RETURN_OK;
8002
8003}
8004
8005INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8006{
8007#if 0
8008 /*char buf[1024] = {0};
8009 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8010 _syscmd(cmd, buf, sizeof(buf));*/
8011
8012 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8013 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8014 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8015 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8016
8017 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.
8018 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].
8019 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].
8020 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].
8021 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8022 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8023
8024 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8025 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8026 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8027 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.
8028 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.
8029 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.
8030 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.
8031 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.
8032 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.
8033 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.
8034 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8035#endif
8036
8037 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008038 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008039 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008040 char pipeCmd[128] = {0};
8041 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008042 wifi_ssidTrafficStats2_t *out = output_struct;
8043
developerce736392022-09-13 15:24:34 +08008044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008045 if (!output_struct)
8046 return RETURN_ERR;
8047
developerce736392022-09-13 15:24:34 +08008048 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8049 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8050 GetInterfaceName(interface_name, HConf_file);
8051 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008052
developer06a01d92022-09-07 16:32:39 +08008053 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008054 if (fp == NULL) {
8055 fprintf(stderr, "%s: popen failed\n", __func__);
8056 return RETURN_ERR;
8057 }
8058 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008059
developerce736392022-09-13 15:24:34 +08008060 if (strlen(str) == 0) // interface not exist
8061 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008062
developerce736392022-09-13 15:24:34 +08008063 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8064 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008065 pclose(fp);
8066
developerce736392022-09-13 15:24:34 +08008067 memset(str, 0, sizeof(str));
8068 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008069 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008070 if (fp == NULL) {
8071 fprintf(stderr, "%s: popen failed\n", __func__);
8072 return RETURN_ERR;
8073 }
8074 fgets(str, sizeof(str), fp);
8075
8076 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8077 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008078 pclose(fp);
developerce736392022-09-13 15:24:34 +08008079
8080 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8081 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8082
8083 // Not supported
8084 output_struct->ssid_RetransCount = 0;
8085 output_struct->ssid_FailedRetransCount = 0;
8086 output_struct->ssid_RetryCount = 0;
8087 output_struct->ssid_MultipleRetryCount = 0;
8088 output_struct->ssid_ACKFailureCount = 0;
8089 output_struct->ssid_AggregatedPacketCount = 0;
8090
developer06a01d92022-09-07 16:32:39 +08008091 return RETURN_OK;
8092}
8093
8094//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).
8095INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8096{
8097 char output_val[16]={'\0'};
8098 char config_file[MAX_BUF_SIZE] = {0};
8099
8100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8101 if (!output)
8102 return RETURN_ERR;
8103 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8104 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8105
8106 if( strcmp(output_val,"1") == 0 )
8107 *output = TRUE;
8108 else
8109 *output = FALSE;
8110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8111
8112 return RETURN_OK;
8113}
8114
8115INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8116{
8117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8118 char str[MAX_BUF_SIZE]={'\0'};
8119 char string[MAX_BUF_SIZE]={'\0'};
8120 char cmd[MAX_CMD_SIZE]={'\0'};
8121 char *ch;
8122 char config_file[MAX_BUF_SIZE] = {0};
8123 struct params params;
8124
8125 if(enable == TRUE)
8126 strcpy(string,"1");
8127 else
8128 strcpy(string,"0");
8129
8130 params.name = "ap_isolate";
8131 params.value = string;
8132
8133 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8134 wifi_hostapdWrite(config_file,&params,1);
8135 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8136
8137 return RETURN_OK;
8138}
8139
8140INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8141{
8142 if (NULL == output_dBm)
8143 return RETURN_ERR;
8144
8145 *output_dBm = 0;
8146 return RETURN_OK;
8147}
8148
8149INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8150{
8151 return RETURN_OK;
8152}
8153INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8154{
8155 return RETURN_OK;
8156}
8157INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8158{
8159 return RETURN_OK;
8160}
8161INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8162{
8163 return RETURN_OK;
8164}
8165INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8166{
8167 return RETURN_OK;
8168}
8169INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8170{
8171 char config_file[MAX_BUF_SIZE] = {0};
8172 struct params list;
8173
8174 list.name = "bss_transition";
8175 list.value = activate?"1":"0";
8176 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8177 wifi_hostapdWrite(config_file, &list, 1);
8178
8179 return RETURN_OK;
8180}
8181wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8182
8183void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8184{
8185 return;
8186}
8187
8188INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8189{
8190 // TODO Implement me!
8191 return RETURN_OK;
8192}
8193
8194INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8195{
developera3c68b92022-09-13 15:27:29 +08008196 char file_name[128] = {0};
8197 char buf[128] = {0};
8198 FILE *f = NULL;
8199
8200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8201
8202 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8203 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8204 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8205 f = fopen(file_name, "w");
8206 if (f == NULL)
8207 return RETURN_ERR;
8208 // For mode == 0 is to disable filter, just don't write to the file.
8209 if (mode)
8210 fprintf(f, "%s", essid);
8211
8212 fclose(f);
8213 }
8214 } else { // special case, need to set AP's SSID as filter for each radio.
8215 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8216 f = fopen(file_name, "w");
8217 if (f == NULL)
8218 return RETURN_ERR;
8219
8220 // For mode == 0 is to disable filter, just don't write to the file.
8221 if (mode)
8222 fprintf(f, "%s", essid);
8223
8224 fclose(f);
8225 }
8226
8227 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008228 return RETURN_OK;
8229}
8230
8231INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8232{
8233 // TODO Implement me!
8234 //Apply wifi_pushRadioChannel() instantly
8235 return RETURN_ERR;
8236}
8237
8238INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8239{
8240 // TODO Implement me!
8241 return RETURN_OK;
8242}
8243
8244#ifdef HAL_NETLINK_IMPL
8245static int tidStats_callback(struct nl_msg *msg, void *arg) {
8246 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8247 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8248 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8249 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8250 int rem , tid_index = 0;
8251
8252 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8253 wifi_associated_dev_tid_entry_t *stats_entry;
8254
8255 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8256 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8257 };
8258 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8259 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8260 };
8261
8262 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8263 genlmsg_attrlen(gnlh, 0), NULL);
8264
8265
8266 if (!tb[NL80211_ATTR_STA_INFO]) {
8267 fprintf(stderr, "station stats missing!\n");
8268 return NL_SKIP;
8269 }
8270
8271 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8272 tb[NL80211_ATTR_STA_INFO],
8273 stats_policy)) {
8274 fprintf(stderr, "failed to parse nested attributes!\n");
8275 return NL_SKIP;
8276 }
8277
8278 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8279 {
8280 stats_entry = &out->tid_array[tid_index];
8281
8282 stats_entry->tid = tid_index;
8283 stats_entry->ac = _tid_ac_index_get[tid_index];
8284
8285 if(sinfo[NL80211_STA_INFO_TID_STATS])
8286 {
8287 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8288 printf("failed to parse nested stats attributes!");
8289 return NL_SKIP;
8290 }
8291 }
8292 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8293 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8294
8295 if(tid_index < (PS_MAX_TID - 1))
8296 tid_index++;
8297 }
8298 //ToDo: sum_time_ms, ewma_time_ms
8299 return NL_SKIP;
8300}
8301#endif
8302
8303INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8304{
8305#ifdef HAL_NETLINK_IMPL
8306 Netlink nl;
8307 char if_name[10];
8308
8309 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8310
8311 nl.id = initSock80211(&nl);
8312
8313 if (nl.id < 0) {
8314 fprintf(stderr, "Error initializing netlink \n");
8315 return -1;
8316 }
8317
8318 struct nl_msg* msg = nlmsg_alloc();
8319
8320 if (!msg) {
8321 fprintf(stderr, "Failed to allocate netlink message.\n");
8322 nlfree(&nl);
8323 return -2;
8324 }
8325
8326 genlmsg_put(msg,
8327 NL_AUTO_PORT,
8328 NL_AUTO_SEQ,
8329 nl.id,
8330 0,
8331 0,
8332 NL80211_CMD_GET_STATION,
8333 0);
8334
8335 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8336 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8337 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
8338 nl_send_auto(nl.socket, msg);
8339 nl_recvmsgs(nl.socket, nl.cb);
8340 nlmsg_free(msg);
8341 nlfree(&nl);
8342 return RETURN_OK;
8343#else
8344//iw implementation
8345#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
8346#define TOTAL_MAX_LINES 50
8347
8348 char buf[256] = {'\0'}; /* or other suitable maximum line size */
8349 char if_name[10];
8350 FILE *fp=NULL;
8351 char pipeCmd[1024]= {'\0'};
8352 int lines,tid_index=0;
8353 char mac_addr[20] = {'\0'};
8354
8355 wifi_associated_dev_tid_entry_t *stats_entry;
8356
8357 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8358 strcpy(mac_addr,clientMacAddress);
8359
8360 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
8361 fp= popen(pipeCmd,"r");
8362 if(fp == NULL)
8363 {
8364 perror("popen for station dump failed\n");
8365 return RETURN_ERR;
8366 }
8367 pclose(fp);
8368
8369 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
8370 fp=popen(pipeCmd,"r");
8371 if(fp == NULL)
8372 {
8373 perror("popen for grep station failed\n");
8374 return RETURN_ERR;
8375 }
8376 else if(fgets(buf,sizeof(buf),fp) != NULL)
8377 lines=atoi(buf);
8378 else
8379 {
8380 pclose(fp);
8381 fprintf(stderr,"No devices are connected \n");
8382 return RETURN_ERR;
8383 }
8384 pclose(fp);
8385
8386 if(lines == 1)
8387 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
8388
8389 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
8390 {
8391 stats_entry = &tid_stats->tid_array[tid_index];
8392 stats_entry->tid = tid_index;
8393
8394 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);
8395
8396 fp=popen(pipeCmd,"r");
8397 if(fp ==NULL)
8398 {
8399 perror("Failed to read from tid file \n");
8400 return RETURN_ERR;
8401 }
8402 else if(fgets(buf,sizeof(buf),fp) != NULL)
8403 stats_entry->num_msdus = atol(buf);
8404
8405 pclose(fp);
8406 stats_entry->ac = _tid_ac_index_get[tid_index];
8407// TODO:
8408// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
8409// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
8410 }
8411 return RETURN_OK;
8412#endif
8413}
8414
8415
8416INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
8417{
8418 // TODO Implement me!
8419 return RETURN_OK;
8420}
8421
8422
8423INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
8424{
8425 // TODO Implement me!
8426 return RETURN_ERR;
8427}
8428
8429INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
8430{
8431 // TODO Implement me!
8432 return RETURN_ERR;
8433}
8434
8435INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8436{
8437 // TODO Implement me!
8438 return RETURN_ERR;
8439}
8440
8441INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8442{
8443 // TODO Implement me!
8444 return RETURN_ERR;
8445}
8446
8447INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
8448{
8449 // TODO Implement me!
8450 return RETURN_ERR;
8451}
8452
8453INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
8454{
8455 // TODO Implement me!
8456 return RETURN_ERR;
8457}
8458
8459INT wifi_steering_eventUnregister(void)
8460{
8461 // TODO Implement me!
8462 return RETURN_ERR;
8463}
8464
8465INT wifi_delApAclDevices(INT apIndex)
8466{
8467#if 0
8468 char cmd[MAX_BUF_SIZE] = {0};
8469 char buf[MAX_BUF_SIZE] = {0};
8470
8471 /* Not reset proof solution */
8472 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
8473 if(_syscmd(cmd,buf,sizeof(buf)))
8474 return RETURN_ERR;
8475#endif
developere6aafda2022-09-13 14:59:28 +08008476 char cmd[MAX_CMD_SIZE]={0};
8477 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08008478
developere6aafda2022-09-13 14:59:28 +08008479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8480 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
8481 if(_syscmd(cmd, buf, sizeof(buf)))
8482 return RETURN_ERR;
8483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008484
8485 return RETURN_OK;
8486}
8487
8488#ifdef HAL_NETLINK_IMPL
8489static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
8490 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8491 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8492 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8493 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8494 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8495 char mac_addr[20],dev[20];
8496
8497 nla_parse(tb,
8498 NL80211_ATTR_MAX,
8499 genlmsg_attrdata(gnlh, 0),
8500 genlmsg_attrlen(gnlh, 0),
8501 NULL);
8502
8503 if(!tb[NL80211_ATTR_STA_INFO]) {
8504 fprintf(stderr, "sta stats missing!\n");
8505 return NL_SKIP;
8506 }
8507
8508 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8509 fprintf(stderr, "failed to parse nested attributes!\n");
8510 return NL_SKIP;
8511 }
8512 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8513
8514 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8515
8516 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
8517 fprintf(stderr, "failed to parse nested rate attributes!");
8518 return NL_SKIP;
8519 }
8520
8521 if(sinfo[NL80211_STA_INFO_TID_STATS])
8522 {
8523 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8524 printf("failed to parse nested stats attributes!");
8525 return NL_SKIP;
8526 }
8527 }
8528
8529 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
8530 {
8531 printf("Type is VHT\n");
8532 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8533 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8534
8535 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8536 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
8537 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8538 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8539 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8540 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8541 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8542 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8543 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
8544 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8545 }
8546 else
8547 {
8548 printf(" OFDM or CCK \n");
8549 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8550 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
8551 }
8552
8553 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
8554 if(rinfo[NL80211_RATE_INFO_MCS])
8555 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8556 }
8557 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
8558 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
8559 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
8560 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
8561
8562 if(stats_info[NL80211_TID_STATS_RX_MSDU])
8563 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
8564
8565 if (sinfo[NL80211_STA_INFO_SIGNAL])
8566 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
8567 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
8568 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
8569 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
8570 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
8571 //rssi_array need to be filled
8572 return NL_SKIP;
8573}
8574#endif
8575
8576INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8577{
8578#ifdef HAL_NETLINK_IMPL
8579 Netlink nl;
8580 char if_name[10];
8581
8582 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
8583
8584 if (*output_array_size <= 0)
8585 return RETURN_OK;
8586
8587 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8588 nl.id = initSock80211(&nl);
8589
8590 if (nl.id < 0) {
8591 fprintf(stderr, "Error initializing netlink \n");
8592 return 0;
8593 }
8594
8595 struct nl_msg* msg = nlmsg_alloc();
8596
8597 if (!msg) {
8598 fprintf(stderr, "Failed to allocate netlink message.\n");
8599 nlfree(&nl);
8600 return 0;
8601 }
8602
8603 genlmsg_put(msg,
8604 NL_AUTO_PORT,
8605 NL_AUTO_SEQ,
8606 nl.id,
8607 0,
8608 0,
8609 NL80211_CMD_GET_STATION,
8610 0);
8611
8612 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
8613 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8614 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
8615 nl_send_auto(nl.socket, msg);
8616 nl_recvmsgs(nl.socket, nl.cb);
8617 nlmsg_free(msg);
8618 nlfree(&nl);
8619 return RETURN_OK;
8620#else
8621 //TODO Implement me
8622 return RETURN_OK;
8623#endif
8624}
8625
8626#ifdef HAL_NETLINK_IMPL
8627static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
8628 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8629 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8630 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8631 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8632 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8633 char mac_addr[20],dev[20];
8634
8635 nla_parse(tb,
8636 NL80211_ATTR_MAX,
8637 genlmsg_attrdata(gnlh, 0),
8638 genlmsg_attrlen(gnlh, 0),
8639 NULL);
8640
8641 if(!tb[NL80211_ATTR_STA_INFO]) {
8642 fprintf(stderr, "sta stats missing!\n");
8643 return NL_SKIP;
8644 }
8645
8646 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8647 fprintf(stderr, "failed to parse nested attributes!\n");
8648 return NL_SKIP;
8649 }
8650
8651 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8652
8653 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8654
8655 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
8656 fprintf(stderr, "failed to parse nested rate attributes!");
8657 return NL_SKIP;
8658 }
8659
8660 if(sinfo[NL80211_STA_INFO_TID_STATS])
8661 {
8662 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8663 printf("failed to parse nested stats attributes!");
8664 return NL_SKIP;
8665 }
8666 }
8667 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
8668 {
8669 printf("Type is VHT\n");
8670 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8671 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8672
8673 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8674 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
8675 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8676 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8677 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8678 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8679 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8680 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
8681 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
8682 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8683 }
8684 else
8685 {
8686 printf(" OFDM or CCK \n");
8687 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
8688 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
8689 }
8690
8691 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
8692 if(rinfo[NL80211_RATE_INFO_MCS])
8693 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8694 }
8695
8696 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
8697 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
8698 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
8699 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
8700
8701 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
8702 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
8703 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
8704
8705 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8706 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8707
8708 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
8709 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
8710
8711 if(sinfo[NL80211_STA_INFO_TX_FAILED])
8712 ((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]);
8713
8714 return NL_SKIP;
8715}
8716#endif
8717
8718INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8719{
8720#ifdef HAL_NETLINK_IMPL
8721 Netlink nl;
8722 char if_name[10];
8723
8724 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
8725
8726 if (*output_array_size <= 0)
8727 return RETURN_OK;
8728
8729 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8730
8731 nl.id = initSock80211(&nl);
8732
8733 if(nl.id < 0) {
8734 fprintf(stderr, "Error initializing netlink \n");
8735 return 0;
8736 }
8737
8738 struct nl_msg* msg = nlmsg_alloc();
8739
8740 if(!msg) {
8741 fprintf(stderr, "Failed to allocate netlink message.\n");
8742 nlfree(&nl);
8743 return 0;
8744 }
8745
8746 genlmsg_put(msg,
8747 NL_AUTO_PORT,
8748 NL_AUTO_SEQ,
8749 nl.id,
8750 0,
8751 0,
8752 NL80211_CMD_GET_STATION,
8753 0);
8754
8755 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8756 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8757 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
8758 nl_send_auto(nl.socket, msg);
8759 nl_recvmsgs(nl.socket, nl.cb);
8760 nlmsg_free(msg);
8761 nlfree(&nl);
8762 return RETURN_OK;
8763#else
8764 //TODO Implement me
8765 return RETURN_OK;
8766#endif
8767}
8768
8769INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
8770{
8771 // TODO Implement me!
8772 char buf[MAX_BUF_SIZE] = {0};
8773 char config_file[MAX_BUF_SIZE] = {0};
8774
8775 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8776 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
8777 *activate = (strncmp("1",buf,1) == 0);
8778
8779 return RETURN_OK;
8780}
8781
8782INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
8783{
8784 char config_file[MAX_BUF_SIZE] = {0};
8785 struct params list;
8786
8787 list.name = "rrm_neighbor_report";
8788 list.value = activate?"1":"0";
8789 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8790 wifi_hostapdWrite(config_file, &list, 1);
8791
8792 return RETURN_OK;
8793}
8794
8795INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
8796{
8797 char buf[32] = {0};
8798 char config_file[MAX_BUF_SIZE] = {0};
8799
8800 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8801 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
8802 *activate = (strncmp("1",buf,1) == 0);
8803
8804 return RETURN_OK;
8805}
8806#undef HAL_NETLINK_IMPL
8807#ifdef HAL_NETLINK_IMPL
8808static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
8809 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8810 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8811 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
8812 char dev[20];
8813 int freq =0 ;
8814 static int i=0;
8815
8816 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
8817
8818 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
8819 };
8820
8821 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
8822
8823 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8824
8825 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
8826 fprintf(stderr, "survey data missing!\n");
8827 return NL_SKIP;
8828 }
8829
8830 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
8831 {
8832 fprintf(stderr, "failed to parse nested attributes!\n");
8833 return NL_SKIP;
8834 }
8835
8836
8837 if(out[0].array_size == 1 )
8838 {
8839 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
8840 {
8841 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
8842 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
8843 out[0].ch_number = ieee80211_frequency_to_channel(freq);
8844
8845 if (sinfo[NL80211_SURVEY_INFO_NOISE])
8846 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
8847 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
8848 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
8849 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
8850 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
8851 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
8852 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
8853 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
8854 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
8855 if (sinfo[NL80211_SURVEY_INFO_TIME])
8856 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
8857 return NL_STOP;
8858 }
8859 }
8860 else
8861 {
8862 if ( i <= out[0].array_size )
8863 {
8864 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
8865 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
8866 out[i].ch_number = ieee80211_frequency_to_channel(freq);
8867
8868 if (sinfo[NL80211_SURVEY_INFO_NOISE])
8869 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
8870 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
8871 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
8872 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
8873 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
8874 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
8875 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
8876 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
8877 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
8878 if (sinfo[NL80211_SURVEY_INFO_TIME])
8879 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
8880 }
8881 }
8882
8883 i++;
8884 return NL_SKIP;
8885}
8886#endif
8887
8888static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
8889{
8890 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
8891 FILE *fp;
8892
8893 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
8894 {
8895 printf("Creating Frequency-Channel Map\n");
8896 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
8897 }
8898 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
8899 if((fp = popen(command, "r")))
8900 {
8901 fgets(output, sizeof(output), fp);
8902 *freqMHz = atoi(output);
8903 fclose(fp);
8904 }
8905
8906 return 0;
8907}
8908
8909static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
8910{
8911 int freqMHz = -1;
8912 char cmd[MAX_CMD_SIZE] = {'\0'};
8913
8914 ieee80211_channel_to_frequency(channel, &freqMHz);
8915 if (freqMHz == -1) {
8916 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
8917 return -1;
8918 }
8919
8920 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
8921 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
8922 radioIndex, freqMHz);
8923 return -1;
8924 }
8925
8926 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
8927 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
8928 return -1;
8929 }
8930
8931 return 0;
8932}
8933
8934static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
8935{
8936 const char *ptr = buf;
8937 char *key = NULL;
8938 char *val = NULL;
8939 char line[256] = { '\0' };
8940
8941 while (ptr = get_line_from_str_buf(ptr, line)) {
8942 if (strstr(line, "Frequency")) continue;
8943
8944 key = strtok(line, ":");
8945 val = strtok(NULL, " ");
8946 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
8947
8948 if (!strcmp(key, "noise")) {
8949 sscanf(val, "%d", &stats->ch_noise);
8950 if (stats->ch_noise == 0) {
8951 // Workaround for missing noise information.
8952 // Assume -95 for 2.4G and -103 for 5G
8953 if (radioIndex == 0) stats->ch_noise = -95;
8954 if (radioIndex == 1) stats->ch_noise = -103;
8955 }
8956 }
8957 else if (!strcmp(key, "channel active time")) {
8958 sscanf(val, "%llu", &stats->ch_utilization_total);
8959 }
8960 else if (!strcmp(key, "channel busy time")) {
8961 sscanf(val, "%llu", &stats->ch_utilization_busy);
8962 }
8963 else if (!strcmp(key, "channel receive time")) {
8964 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
8965 }
8966 else if (!strcmp(key, "channel transmit time")) {
8967 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
8968 }
8969 };
8970
8971 return 0;
8972}
8973
8974INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
8975{
8976 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8977#ifdef HAL_NETLINK_IMPL
8978 Netlink nl;
8979 wifi_channelStats_t_loc local[array_size];
8980 char if_name[10];
8981
8982 local[0].array_size = array_size;
8983
8984 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8985
8986 nl.id = initSock80211(&nl);
8987
8988 if (nl.id < 0) {
8989 fprintf(stderr, "Error initializing netlink \n");
8990 return -1;
8991 }
8992
8993 struct nl_msg* msg = nlmsg_alloc();
8994
8995 if (!msg) {
8996 fprintf(stderr, "Failed to allocate netlink message.\n");
8997 nlfree(&nl);
8998 return -2;
8999 }
9000
9001 genlmsg_put(msg,
9002 NL_AUTO_PORT,
9003 NL_AUTO_SEQ,
9004 nl.id,
9005 0,
9006 NLM_F_DUMP,
9007 NL80211_CMD_GET_SURVEY,
9008 0);
9009
9010 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9011 nl_send_auto(nl.socket, msg);
9012 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9013 nl_recvmsgs(nl.socket, nl.cb);
9014 nlmsg_free(msg);
9015 nlfree(&nl);
9016 //Copying the Values
9017 for(int i=0;i<array_size;i++)
9018 {
9019 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9020 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9021 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9022 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9023 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9024 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9025 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9026 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9027 }
9028#else
9029 ULONG channel = 0;
9030 int i;
9031 int number_of_channels = array_size;
9032 char buf[512];
9033 INT ret;
9034 wifi_channelStats_t tmp_stats;
9035
9036 if (number_of_channels == 0) {
9037 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9038 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9039 return RETURN_ERR;
9040 }
9041 number_of_channels = 1;
9042 input_output_channelStats_array[0].ch_number = channel;
9043 }
9044
9045 for (i = 0; i < number_of_channels; i++) {
9046
9047 input_output_channelStats_array[i].ch_noise = 0;
9048 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9049 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9050 input_output_channelStats_array[i].ch_utilization_busy = 0;
9051 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9052 input_output_channelStats_array[i].ch_utilization_total = 0;
9053
9054 memset(buf, 0, sizeof(buf));
9055 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9056 return RETURN_ERR;
9057 }
9058 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9059 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9060 return RETURN_ERR;
9061 }
9062
9063 // XXX: fake missing 'self' counter which is not available in iw survey output
9064 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9065 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9066
9067 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9068 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9069 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9070 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9071 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9072
9073 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",
9074 __func__,
9075 input_output_channelStats_array[i].ch_number,
9076 input_output_channelStats_array[i].ch_noise,
9077 input_output_channelStats_array[i].ch_utilization_total,
9078 input_output_channelStats_array[i].ch_utilization_busy,
9079 input_output_channelStats_array[i].ch_utilization_busy_rx,
9080 input_output_channelStats_array[i].ch_utilization_busy_tx,
9081 input_output_channelStats_array[i].ch_utilization_busy_self,
9082 input_output_channelStats_array[i].ch_utilization_busy_ext);
9083 }
9084#endif
9085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9086 return RETURN_OK;
9087}
9088#define HAL_NETLINK_IMPL
9089
9090/* Hostapd events */
9091
9092#ifndef container_of
9093#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9094#define container_of(ptr, type, member) \
9095 ((type *)((char *)ptr - offset_of(type, member)))
9096#endif /* container_of */
9097
9098struct ctrl {
9099 char sockpath[128];
9100 char sockdir[128];
9101 char bss[IFNAMSIZ];
9102 char reply[4096];
9103 int ssid_index;
9104 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9105 void (*overrun)(struct ctrl *ctrl);
9106 struct wpa_ctrl *wpa;
9107 unsigned int ovfl;
9108 size_t reply_len;
9109 int initialized;
9110 ev_timer retry;
9111 ev_timer watchdog;
9112 ev_stat stat;
9113 ev_io io;
9114};
9115static wifi_newApAssociatedDevice_callback clients_connect_cb;
9116static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9117static struct ctrl wpa_ctrl[MAX_APS];
9118static int initialized;
9119
9120static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9121{
9122 char cbuf[256] = {};
9123 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9124 struct cmsghdr *cmsg;
9125 unsigned int ovfl = ctrl->ovfl;
9126 unsigned int drop;
9127
9128 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9129 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9130 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9131 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9132
9133 drop = ovfl - ctrl->ovfl;
9134 ctrl->ovfl = ovfl;
9135
9136 return drop;
9137}
9138
9139static void ctrl_close(struct ctrl *ctrl)
9140{
9141 if (ctrl->io.cb)
9142 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9143 if (ctrl->retry.cb)
9144 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9145 if (!ctrl->wpa)
9146 return;
9147
9148 wpa_ctrl_detach(ctrl->wpa);
9149 wpa_ctrl_close(ctrl->wpa);
9150 ctrl->wpa = NULL;
9151 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9152}
9153
9154static void ctrl_process(struct ctrl *ctrl)
9155{
9156 const char *str;
9157 int drops;
9158 int level;
9159 int err;
9160
9161 /* Example events:
9162 *
9163 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9164 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9165 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9166 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9167 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9168 */
9169 if (!(str = index(ctrl->reply, '>')))
9170 return;
9171 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9172 return;
9173
9174 str++;
9175
9176 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9177 if (!(str = index(ctrl->reply, ' ')))
9178 return;
9179 wifi_associated_dev_t sta;
9180 memset(&sta, 0, sizeof(sta));
9181
9182 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9183 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9184 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9185
9186 sta.cli_Active=true;
9187
9188 (clients_connect_cb)(ctrl->ssid_index, &sta);
9189 goto handled;
9190 }
9191
9192 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9193 if (!(str = index(ctrl->reply, ' ')))
9194 return;
9195
9196 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9197 goto handled;
9198 }
9199
9200 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9201 printf("CTRL_WPA: handle TERMINATING event\n");
9202 goto retry;
9203 }
9204
9205 if (strncmp("AP-DISABLED", str, 11) == 0) {
9206 printf("CTRL_WPA: handle AP-DISABLED\n");
9207 goto retry;
9208 }
9209
9210 printf("Event not supported!!\n");
9211
9212handled:
9213
9214 if ((drops = ctrl_get_drops(ctrl))) {
9215 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9216 if (ctrl->overrun)
9217 ctrl->overrun(ctrl);
9218 }
9219
9220 return;
9221
9222retry:
9223 printf("WPA_CTRL: closing\n");
9224 ctrl_close(ctrl);
9225 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9226 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9227}
9228
9229static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9230{
9231 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9232 int err;
9233
9234 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9235 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9236 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9237 ctrl->reply[ctrl->reply_len] = 0;
9238 if (err < 0) {
9239 if (errno == EAGAIN || errno == EWOULDBLOCK)
9240 return;
9241 ctrl_close(ctrl);
9242 ev_timer_again(EV_A_ &ctrl->retry);
9243 return;
9244 }
9245
9246 ctrl_process(ctrl);
9247}
9248
9249static int ctrl_open(struct ctrl *ctrl)
9250{
9251 int fd;
9252
9253 if (ctrl->wpa)
9254 return 0;
9255
9256 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9257 if (!ctrl->wpa)
9258 goto err;
9259
9260 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9261 goto err_close;
9262
9263 fd = wpa_ctrl_get_fd(ctrl->wpa);
9264 if (fd < 0)
9265 goto err_detach;
9266
9267 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9268 goto err_detach;
9269
9270 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9271 ev_io_start(EV_DEFAULT_ &ctrl->io);
9272
9273 return 0;
9274
9275err_detach:
9276 wpa_ctrl_detach(ctrl->wpa);
9277err_close:
9278 wpa_ctrl_close(ctrl->wpa);
9279err:
9280 ctrl->wpa = NULL;
9281 return -1;
9282}
9283
9284static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9285{
9286 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9287
9288 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9289 ctrl_open(ctrl);
9290}
9291
9292static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9293{
9294 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9295
9296 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9297 if (ctrl_open(ctrl) == 0) {
9298 printf("WPA_CTRL: retry successful\n");
9299 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9300 }
9301}
9302
9303int ctrl_enable(struct ctrl *ctrl)
9304{
9305 if (ctrl->wpa)
9306 return 0;
9307
9308 if (!ctrl->stat.cb) {
9309 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9310 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
9311 }
9312
9313 if (!ctrl->retry.cb) {
9314 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
9315 }
9316
9317 return ctrl_open(ctrl);
9318}
9319
9320static void
9321ctrl_msg_cb(char *buf, size_t len)
9322{
9323 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
9324
9325 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
9326 ctrl_process(ctrl);
9327}
9328
9329static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
9330{
9331 int err;
9332
9333 if (!ctrl->wpa)
9334 return -1;
9335 if (*reply_len < 2)
9336 return -1;
9337
9338 (*reply_len)--;
9339 ctrl->reply_len = sizeof(ctrl->reply);
9340 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
9341 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
9342 if (err < 0)
9343 return err;
9344
9345 if (ctrl->reply_len > *reply_len)
9346 ctrl->reply_len = *reply_len;
9347
9348 *reply_len = ctrl->reply_len;
9349 memcpy(reply, ctrl->reply, *reply_len);
9350 reply[*reply_len - 1] = 0;
9351 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
9352 return 0;
9353}
9354
9355static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
9356{
9357 const char *pong = "PONG";
9358 const char *ping = "PING";
9359 char reply[1024];
9360 size_t len = sizeof(reply);
9361 int err;
9362 ULONG s, snum;
9363 INT ret;
9364 BOOL status;
9365
9366 printf("WPA_CTRL: watchdog cb\n");
9367
9368 ret = wifi_getSSIDNumberOfEntries(&snum);
9369 if (ret != RETURN_OK) {
9370 printf("%s: failed to get SSID count", __func__);
9371 return;
9372 }
9373
9374 if (snum > MAX_APS) {
9375 printf("more ssid than supported! %lu\n", snum);
9376 return;
9377 }
9378
9379 for (s = 0; s < snum; s++) {
9380 if (wifi_getApEnable(s, &status) != RETURN_OK) {
9381 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
9382 continue;
9383 }
9384 if (status == false) continue;
9385
9386 memset(reply, 0, sizeof(reply));
9387 len = sizeof(reply);
9388 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
9389 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
9390 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
9391 continue;
9392
9393 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
9394 ctrl_close(&wpa_ctrl[s]);
9395 printf("WPA_CTRL: ev_timer_again %d\n", s);
9396 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
9397 }
9398}
9399
9400static int init_wpa()
9401{
9402 int ret = 0, i = 0;
9403 ULONG s, snum;
9404
9405 ret = wifi_getSSIDNumberOfEntries(&snum);
9406 if (ret != RETURN_OK) {
9407 printf("%s: failed to get SSID count", __func__);
9408 return RETURN_ERR;
9409 }
9410
9411 if (snum > MAX_APS) {
9412 printf("more ssid than supported! %lu\n", snum);
9413 return RETURN_ERR;
9414 }
9415
9416 for (s = 0; s < snum; s++) {
9417 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
9418 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
9419 wpa_ctrl[s].ssid_index = s;
9420 ctrl_enable(&wpa_ctrl[s]);
9421 }
9422
9423 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
9424 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
9425
9426 initialized = 1;
9427 printf("WPA_CTRL: initialized\n");
9428
9429 return RETURN_OK;
9430}
9431
9432void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
9433{
9434 clients_connect_cb = callback_proc;
9435 if (!initialized)
9436 init_wpa();
9437}
9438
9439void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
9440{
9441 clients_disconnect_cb = callback_proc;
9442 if (!initialized)
9443 init_wpa();
9444}
9445
9446INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
9447{
9448 // TODO Implement me!
9449 return RETURN_ERR;
9450}
9451
9452INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
9453{
9454 // TODO Implement me!
9455 return RETURN_ERR;
9456}
9457
9458INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
9459{
9460 int i;
9461 char cmd[256];
9462 char channel_numbers_buf[256];
9463 char dfs_state_buf[256];
9464 char line[256];
9465 const char *ptr;
9466
9467 memset(cmd, 0, sizeof(cmd));
9468 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
9469 memset(line, 0, sizeof(line));
9470 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9471 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
9472
9473 if (radioIndex == 0) { // 2.4G - all allowed
9474 if (outputMapSize < 11) {
9475 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
9476 return RETURN_ERR;
9477 }
9478
9479 for (i = 0; i < 11; i++) {
9480 outputMap[i].ch_number = i + 1;
9481 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9482 }
9483
9484 return RETURN_OK;
9485 }
9486
9487 if (radioIndex == 1) { // 5G
9488// Example output of iw list:
9489//
9490// Frequencies:
9491// * 5180 MHz [36] (17.0 dBm)
9492// * 5200 MHz [40] (17.0 dBm)
9493// * 5220 MHz [44] (17.0 dBm)
9494// * 5240 MHz [48] (17.0 dBm)
9495// * 5260 MHz [52] (23.0 dBm) (radar detection)
9496// DFS state: usable (for 78930 sec)
9497// DFS CAC time: 60000 ms
9498// * 5280 MHz [56] (23.0 dBm) (radar detection)
9499// DFS state: usable (for 78930 sec)
9500// DFS CAC time: 60000 ms
9501// * 5300 MHz [60] (23.0 dBm) (radar detection)
9502// DFS state: usable (for 78930 sec)
9503// DFS CAC time: 60000 ms
9504// * 5320 MHz [64] (23.0 dBm) (radar detection)
9505// DFS state: usable (for 78930 sec)
9506// DFS CAC time: 60000 ms
9507// * 5500 MHz [100] (disabled)
9508// * 5520 MHz [104] (disabled)
9509// * 5540 MHz [108] (disabled)
9510// * 5560 MHz [112] (disabled)
9511//
9512// Below command should fetch channel numbers of each enabled channel in 5GHz band:
9513 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
9514 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
9515 return RETURN_ERR;
9516 }
9517
9518 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
9519 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9520 return RETURN_ERR;
9521 }
9522
9523 ptr = channel_numbers_buf;
9524 i = 0;
9525 while (ptr = get_line_from_str_buf(ptr, line)) {
9526 if (i >= outputMapSize) {
9527 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
9528 return RETURN_ERR;
9529 }
9530 sscanf(line, "%d", &outputMap[i].ch_number);
9531
9532 memset(cmd, 0, sizeof(cmd));
9533 // Below command should fetch string for DFS state (usable, available or unavailable)
9534 // Example line: "DFS state: usable (for 78930 sec)"
9535 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) {
9536 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
9537 return RETURN_ERR;
9538 }
9539
9540 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9541 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
9542 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9543 return RETURN_ERR;
9544 }
9545
9546 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
9547
9548 if (!strcmp(dfs_state_buf, "usable")) {
9549 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
9550 } else if (!strcmp(dfs_state_buf, "available")) {
9551 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
9552 } else if (!strcmp(dfs_state_buf, "unavailable")) {
9553 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
9554 } else {
9555 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9556 }
9557 i++;
9558 }
9559
9560 return RETURN_OK;
9561 }
9562
9563 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
9564 return RETURN_ERR;
9565}
9566
9567INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
9568{
9569 // TODO Implement me!
9570 return RETURN_ERR;
9571}
9572
9573INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
9574{
9575 return RETURN_OK;
9576}
9577
9578INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
9579{
9580 // TODO Implement me!
9581 return RETURN_ERR;
9582}
9583
9584INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
9585{
9586 // TODO API refrence Implementaion is present on RPI hal
9587 return RETURN_ERR;
9588}
9589
9590INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
9591{
9592 //TO-Do Implement this
9593 txpwr_pcntg = 0;
9594 return RETURN_OK;
9595}
9596
9597INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
9598{
9599 //Zero-wait DFS not supported
9600 return RETURN_ERR;
9601}
9602
9603INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
9604{
9605 //Zero-wait DFS not supported
9606 return RETURN_ERR;
9607}
9608
9609INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
9610{
9611 *supported = false;
9612 return RETURN_OK;
9613}
9614
developer454b9462022-09-13 15:29:16 +08009615INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
9616{
9617 char cmd[128] = {0};
9618 char buf[64] = {0};
9619 char band_str[8] = {0};
9620 char GI[8] = {0};
9621 int tmp = 0;
9622 BOOL ax_mode = FALSE;
9623 BOOL short_GI = FALSE;
9624 FILE *f = NULL;
9625 wifi_band band;
9626
9627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9628
9629 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
9630 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
9631 return RETURN_ERR;
9632 }
9633 if (strstr(buf, "ax") != NULL)
9634 ax_mode = TRUE;
9635
9636 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
9637 short_GI = TRUE;
9638 strcpy(GI, "0.4");
9639 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
9640 strcpy(GI, "1.6");
9641 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
9642 strcpy(GI, "3.2");
9643 else // default
9644 strcpy(GI, "0.8");
9645
9646 band = wifi_index_to_band(radio_index);
9647 if (band == band_2_4)
9648 strcpy(band_str, "2.4");
9649 else if (band == band_5)
9650 strcpy(band_str, "5");
9651 else if (band == band_6)
9652 strcpy(band_str, "6");
9653 else {
9654 wifi_dbg_printf("%s: invalid band\n");
9655 return RETURN_ERR;
9656 }
9657
9658 if (ax_mode == TRUE)
9659 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
9660 else
9661 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
9662 _syscmd(cmd, buf, sizeof(buf));
9663
9664 // Record GI for get GI function
9665 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
9666 f = fopen(buf, "w");
9667 if (f != NULL) {
9668 fprintf(f, "%s", GI);
9669 }
9670 fclose(f);
9671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9672 return RETURN_OK;
9673}
9674
9675INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
9676{
9677 char buf[32] = {0};
9678 char cmd[64] = {0};
9679
9680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9681
9682 if (guard_interval == NULL)
9683 return RETURN_ERR;
9684
9685 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
9686 _syscmd(cmd, buf, sizeof(buf));
9687
9688 if (strncmp(buf, "0.4", 3) == 0)
9689 *guard_interval = wifi_guard_interval_400;
9690 else if (strncmp(buf, "0.8", 3) == 0)
9691 *guard_interval = wifi_guard_interval_800;
9692 else if (strncmp(buf, "1.6", 3) == 0)
9693 *guard_interval = wifi_guard_interval_1600;
9694 else if (strncmp(buf, "3.2", 3) == 0)
9695 *guard_interval = wifi_guard_interval_3200;
9696 else
9697 *guard_interval = wifi_guard_interval_auto;
9698
9699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9700 return RETURN_OK;
9701}
9702
developer06a01d92022-09-07 16:32:39 +08009703/* multi-psk support */
9704INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
9705{
9706 char cmd[256];
9707
9708 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
9709 AP_PREFIX,
9710 apIndex,
9711 mac[0],
9712 mac[1],
9713 mac[2],
9714 mac[3],
9715 mac[4],
9716 mac[5]
9717 );
9718 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
9719 _syscmd(cmd, key->wifi_keyId, 64);
9720
9721
9722 return RETURN_OK;
9723}
9724
9725INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
9726{
9727 FILE *fd = NULL;
9728 char fname[100];
9729 char cmd[128] = {0};
9730 char out[64] = {0};
9731 wifi_key_multi_psk_t * key = NULL;
9732 if(keysNumber < 0)
9733 return RETURN_ERR;
9734
9735 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
9736 fd = fopen(fname, "w");
9737 if (!fd) {
9738 return RETURN_ERR;
9739 }
9740 key= (wifi_key_multi_psk_t *) keys;
9741 for(int i=0; i<keysNumber; ++i, key++) {
9742 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
9743 }
9744 fclose(fd);
9745
9746 //reload file
9747 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
9748 _syscmd(cmd, out, 64);
9749 return RETURN_OK;
9750}
9751
9752INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
9753{
9754 FILE *fd = NULL;
9755 char fname[100];
9756 char * line = NULL;
9757 char * pos = NULL;
9758 size_t len = 0;
9759 ssize_t read = 0;
9760 INT ret = RETURN_OK;
9761 wifi_key_multi_psk_t *keys_it = NULL;
9762
9763 if (keysNumber < 1) {
9764 return RETURN_ERR;
9765 }
9766
9767 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
9768 fd = fopen(fname, "r");
9769 if (!fd) {
9770 return RETURN_ERR;
9771 }
9772
9773 if (keys == NULL) {
9774 ret = RETURN_ERR;
9775 goto close;
9776 }
9777
9778 keys_it = keys;
9779 while ((read = getline(&line, &len, fd)) != -1) {
9780 //Strip trailing new line if present
9781 if (read > 0 && line[read-1] == '\n') {
9782 line[read-1] = '\0';
9783 }
9784
9785 if(strcmp(line,"keyid=")) {
9786 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
9787 if (!(pos = index(line, ' '))) {
9788 ret = RETURN_ERR;
9789 goto close;
9790 }
9791 pos++;
9792 //Here should be 00:00:00:00:00:00
9793 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
9794 printf("Not supported MAC: %s\n", pos);
9795 }
9796 if (!(pos = index(pos, ' '))) {
9797 ret = RETURN_ERR;
9798 goto close;
9799 }
9800 pos++;
9801
9802 //The rest is PSK
9803 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
9804 keys_it++;
9805
9806 if(--keysNumber <= 0)
9807 break;
9808 }
9809 }
9810
9811close:
9812 free(line);
9813 fclose(fd);
9814 return ret;
9815}
9816/* end of multi-psk support */
9817
9818INT wifi_setNeighborReports(UINT apIndex,
9819 UINT numNeighborReports,
9820 wifi_NeighborReport_t *neighborReports)
9821{
9822 char cmd[256] = { 0 };
9823 char hex_bssid[13] = { 0 };
9824 char bssid[18] = { 0 };
9825 char nr[256] = { 0 };
9826 char ssid[256];
9827 char hex_ssid[256];
9828 INT ret;
9829
9830 /*rmeove all neighbors*/
9831 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
9832 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);
9833 system(cmd);
9834
9835 for(unsigned int i = 0; i < numNeighborReports; i++)
9836 {
9837 memset(ssid, 0, sizeof(ssid));
9838 ret = wifi_getSSIDName(apIndex, ssid);
9839 if (ret != RETURN_OK)
9840 return RETURN_ERR;
9841
9842 memset(hex_ssid, 0, sizeof(hex_ssid));
9843 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
9844 sprintf(hex_ssid + k,"%02x", ssid[j]);
9845
9846 snprintf(hex_bssid, sizeof(hex_bssid),
9847 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
9848 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
9849 snprintf(bssid, sizeof(bssid),
9850 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
9851 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
9852
9853 snprintf(nr, sizeof(nr),
9854 "%s" // bssid
9855 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
9856 "%02hhx" // operclass
9857 "%02hhx" // channel
9858 "%02hhx", // phy_mode
9859 hex_bssid,
9860 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
9861 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
9862 neighborReports[i].opClass,
9863 neighborReports[i].channel,
9864 neighborReports[i].phyTable);
9865
9866 snprintf(cmd, sizeof(cmd),
9867 "hostapd_cli set_neighbor "
9868 "%s " // bssid
9869 "ssid=%s " // ssid
9870 "nr=%s " // nr
9871 "-i %s%d",
9872 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
9873
9874 if (WEXITSTATUS(system(cmd)) != 0)
9875 {
9876 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
9877 }
9878 }
9879
9880 return RETURN_OK;
9881}
9882
9883INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
9884{
9885 return RETURN_OK;
9886}
9887
9888#ifdef _WIFI_HAL_TEST_
9889int main(int argc,char **argv)
9890{
9891 int index;
9892 INT ret=0;
9893 char buf[1024]="";
9894
9895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9896 if(argc<3)
9897 {
9898 if(argc==2)
9899 {
9900 if(!strcmp(argv[1], "init"))
9901 return wifi_init();
9902 if(!strcmp(argv[1], "reset"))
9903 return wifi_reset();
9904 if(!strcmp(argv[1], "wifi_getHalVersion"))
9905 {
9906 char buffer[64];
9907 if(wifi_getHalVersion(buffer)==RETURN_OK)
9908 printf("Version: %s\n", buffer);
9909 else
9910 printf("Error in wifi_getHalVersion\n");
9911 return RETURN_OK;
9912 }
9913 }
9914 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
9915 exit(-1);
9916 }
9917
9918 index = atoi(argv[2]);
9919 if(strstr(argv[1], "wifi_getApName")!=NULL)
9920 {
9921 wifi_getApName(index,buf);
9922 printf("Ap name is %s \n",buf);
9923 return 0;
9924 }
9925 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
9926 {
9927 BOOL b = FALSE;
9928 BOOL *output_bool = &b;
9929 wifi_getRadioAutoChannelEnable(index,output_bool);
9930 printf("Channel enabled = %d \n",b);
9931 return 0;
9932 }
9933 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
9934 {
9935 wifi_getApWpaEncryptionMode(index,buf);
9936 printf("encryption enabled = %s\n",buf);
9937 return 0;
9938 }
9939 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
9940 {
9941 BOOL b = FALSE;
9942 BOOL *output_bool = &b;
9943 wifi_getApSsidAdvertisementEnable(index,output_bool);
9944 printf("advertisment enabled = %d\n",b);
9945 return 0;
9946 }
9947 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
9948 {
9949 if(argc <= 3 )
9950 {
9951 printf("Insufficient arguments \n");
9952 exit(-1);
9953 }
9954
9955 char sta[20] = {'\0'};
9956 ULLONG handle= 0;
9957 strcpy(sta,argv[3]);
9958 mac_address_t st;
9959 mac_addr_aton(st,sta);
9960
9961 wifi_associated_dev_tid_stats_t tid_stats;
9962 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
9963 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
9964 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);
9965 }
9966
9967 if(strstr(argv[1], "getApEnable")!=NULL) {
9968 BOOL enable;
9969 ret=wifi_getApEnable(index, &enable);
9970 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
9971 }
9972 else if(strstr(argv[1], "setApEnable")!=NULL) {
9973 BOOL enable = atoi(argv[3]);
9974 ret=wifi_setApEnable(index, enable);
9975 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
9976 }
9977 else if(strstr(argv[1], "getApStatus")!=NULL) {
9978 char status[64];
9979 ret=wifi_getApStatus(index, status);
9980 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
9981 }
9982 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
9983 {
9984 wifi_getSSIDNameStatus(index,buf);
9985 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
9986 return 0;
9987 }
9988 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
9989 wifi_ssidTrafficStats2_t stats={0};
9990 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
9991 printf("%s %d: returns %d\n", argv[1], index, ret);
9992 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
9993 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
9994 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
9995 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
9996 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
9997 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
9998 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
9999 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10000 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10001 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10002 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10003 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10004 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10005 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10006 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10007 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10008 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10009 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10010 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10011 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10012 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10013 }
10014 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10015 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10016 UINT array_size=0;
10017 UINT i=0;
10018 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10019 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10020 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10021 printf(" neighbor %d:\n", i);
10022 printf(" ap_SSID =%s\n", pt->ap_SSID);
10023 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10024 printf(" ap_Mode =%s\n", pt->ap_Mode);
10025 printf(" ap_Channel =%d\n", pt->ap_Channel);
10026 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10027 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10028 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10029 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10030 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10031 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10032 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10033 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10034 printf(" ap_Noise =%d\n", pt->ap_Noise);
10035 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10036 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10037 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10038 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10039 }
10040 if(neighbor_ap_array)
10041 free(neighbor_ap_array); //make sure to free the list
10042 }
10043 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10044 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10045 UINT array_size=0;
10046 UINT i=0;
10047 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10048 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10049 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10050 printf(" associated_dev %d:\n", i);
10051 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10052 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10053 printf(" cli_SNR =%d\n", pt->cli_SNR);
10054 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10055 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10056 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10057 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10058 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10059 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10060 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10061 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10062 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10063 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10064 }
10065 if(associated_dev_array)
10066 free(associated_dev_array); //make sure to free the list
10067 }
10068
10069 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10070 {
10071#define MAX_ARRAY_SIZE 64
10072 int i, array_size;
10073 char *p, *ch_str;
10074 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10075
10076 if(argc != 5)
10077 {
10078 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10079 exit(-1);
10080 }
10081 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10082
10083 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10084 {
10085 strtok_r(ch_str, ",", &p);
10086 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10087 }
10088 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10089 if(!array_size)
10090 array_size=1;//Need to print current channel statistics
10091 for(i=0; i<array_size; i++)
10092 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10093 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10094 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10095 input_output_channelStats_array[i].ch_number,\
10096 input_output_channelStats_array[i].ch_noise,\
10097 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10098 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10099 input_output_channelStats_array[i].ch_utilization_busy,\
10100 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10101 input_output_channelStats_array[i].ch_utilization_total);
10102 }
10103
10104 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10105 {
10106 if(argc <= 3 )
10107 {
10108 printf("Insufficient arguments \n");
10109 exit(-1);
10110 }
10111 char mac_addr[20] = {'\0'};
10112 wifi_device_t output_struct;
10113 int dev_index = atoi(argv[3]);
10114
10115 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10116 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10117 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);
10118 }
10119
10120 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10121 {
10122 if (argc <= 3)
10123 {
10124 printf("Insufficient arguments\n");
10125 exit(-1);
10126 }
10127 char args[256];
10128 wifi_NeighborReport_t *neighborReports;
10129
10130 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10131 if (!neighborReports)
10132 {
10133 printf("Failed to allocate memory");
10134 exit(-1);
10135 }
10136
10137 for (int i = 3; i < argc; ++i)
10138 {
10139 char *val;
10140 int j = 0;
10141 memset(args, 0, sizeof(args));
10142 strncpy(args, argv[i], sizeof(args));
10143 val = strtok(args, ";");
10144 while (val != NULL)
10145 {
10146 if (j == 0)
10147 {
10148 mac_addr_aton(neighborReports[i - 3].bssid, val);
10149 } else if (j == 1)
10150 {
10151 neighborReports[i - 3].info = strtol(val, NULL, 16);
10152 } else if (j == 2)
10153 {
10154 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10155 } else if (j == 3)
10156 {
10157 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10158 } else if (j == 4)
10159 {
10160 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10161 } else {
10162 printf("Insufficient arguments]n\n");
10163 exit(-1);
10164 }
10165 val = strtok(NULL, ";");
10166 j++;
10167 }
10168 }
10169
10170 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10171 if (ret != RETURN_OK)
10172 {
10173 printf("wifi_setNeighborReports ret = %d", ret);
10174 exit(-1);
10175 }
10176 }
10177 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10178 {
10179 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10180 printf("%s.\n", buf);
10181 else
10182 printf("Error returned\n");
10183 }
10184 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10185 {
10186 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10187 printf("%s.\n", buf);
10188 else
10189 printf("Error returned\n");
10190 }
10191 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10192 {
10193 if (argc <= 2)
10194 {
10195 printf("Insufficient arguments\n");
10196 exit(-1);
10197 }
10198 char buf[64]= {'\0'};
10199 wifi_getRadioOperatingChannelBandwidth(index,buf);
10200 printf("Current bandwidth is %s \n",buf);
10201 return 0;
10202 }
10203 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
10204 {
10205 if (argc <= 5)
10206 {
10207 printf("Insufficient arguments\n");
10208 exit(-1);
10209 }
10210 UINT channel = atoi(argv[3]);
10211 UINT width = atoi(argv[4]);
10212 UINT beacon = atoi(argv[5]);
10213 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
10214 printf("Result = %d", ret);
10215 }
10216
10217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10218 return 0;
10219}
10220
10221#endif
10222
10223#ifdef WIFI_HAL_VERSION_3
10224
10225INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10226{
10227 // The only par-radio parameter is a channel number, however there's a 'dynamic' API
10228 // to change it ("wifi_pushRadioChannel2()") that is used instead.
10229 return RETURN_OK;
10230}
10231
10232INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10233{
10234 INT ret;
10235 char band[128];
10236 ULONG channel;
10237 BOOL enabled;
10238 char buf[256];
10239
10240 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10241 printf("Entering %s index = %d\n", __func__, (int)index);
10242
10243 ret = wifi_getRadioEnable(index, &enabled);
10244 if (ret != RETURN_OK)
10245 {
10246 printf("%s: cannot get enabled state for radio index %d\n", __func__,
10247 index);
10248 return RETURN_ERR;
10249 }
10250 operationParam->enable = enabled;
10251
10252 memset(band, 0, sizeof(band));
10253 ret = wifi_getRadioOperatingFrequencyBand(index, band);
10254 if (ret != RETURN_OK)
10255 {
10256 printf("%s: cannot get radio band for radio index %d\n", __func__, index);
10257 return RETURN_ERR;
10258 }
10259
10260 if (!strcmp(band, "2.4GHz"))
10261 {
10262 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
10263 operationParam->variant = WIFI_80211_VARIANT_N;
10264 }
10265 else if (!strcmp(band, "5GHz"))
10266 {
10267 operationParam->band = WIFI_FREQUENCY_5_BAND;
10268 operationParam->variant = WIFI_80211_VARIANT_AC;
10269 }
10270 else
10271 {
10272 printf("%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
10273 band);
10274 }
10275
10276 memset(buf, 0, sizeof(buf));
10277 ret = wifi_getRadioOperatingChannelBandwidth(index, buf); // XXX: handle errors
10278 // XXX: only handle 20/40/80 modes for now
10279 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
10280 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
10281 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
10282 else
10283 {
10284 printf("%s: Unknown HT mode: '%s'\n", __func__, buf);
10285 operationParam->channelWidth = 0;
10286 }
10287
10288 ret = wifi_getRadioChannel(index, &channel);
10289 if (ret != RETURN_OK)
10290 {
10291 printf("%s: Failed to get channel number for radio index %d\n", __func__, index);
10292 channel = 0;
10293 }
10294 operationParam->channel = channel;
10295 operationParam->csa_beacon_count = 15; // XXX: hardcoded for now
10296
10297 operationParam->countryCode = wifi_countrycode_US; // XXX: hardcoded for now
10298
10299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10300 return RETURN_OK;
10301}
10302
10303static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
10304{
10305 if (radioIndex != 0 && radioIndex != 1)
10306 {
10307 printf("%s: Wrong radio index (%d)\n", __func__, index);
10308 return -1;
10309 }
10310
10311 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
10312 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
10313
10314 return (arrayIndex * 2) + radioIndex;
10315}
10316
10317INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10318{
10319 INT ret;
10320 int i;
10321 BOOL enabled = false;
10322 char buf[256];
10323 wifi_secur_list *secur_item;
10324 int vap_index;
10325 INT mode;
10326 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
10327
10328 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10329 printf("Entering %s index = %d\n", __func__, (int)index);
10330
10331 map->vap_array[index].radio_index = index;
10332 for (i = 0; i < 5; i++)
10333 {
10334 vap_index = array_index_to_vap_index(index, i);
10335 if (vap_index < 0)
10336 {
10337 return RETURN_ERR;
10338 }
10339
10340 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
10341
10342 map->vap_array[i].vap_index = vap_index;
10343
10344 memset(buf, 0, sizeof(buf));
10345 wifi_getApName(vap_index, buf); // XXX: error handling
10346 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
10347
10348 ret = wifi_getSSIDEnable(vap_index, &enabled);
10349 if (ret != RETURN_OK)
10350 {
10351 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
10352 return RETURN_ERR;
10353 }
10354 map->vap_array[i].u.bss_info.enabled = enabled;
10355
10356 memset(buf, 0, sizeof(buf));
10357 wifi_getBaseBSSID(vap_index, buf);
10358 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10359 &map->vap_array[i].u.bss_info.bssid[0],
10360 &map->vap_array[i].u.bss_info.bssid[1],
10361 &map->vap_array[i].u.bss_info.bssid[2],
10362 &map->vap_array[i].u.bss_info.bssid[3],
10363 &map->vap_array[i].u.bss_info.bssid[4],
10364 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
10365
10366 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
10367 map->vap_array[i].u.bss_info.showSsid = enabled;
10368
10369 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
10370 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
10371 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
10372
10373 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
10374 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
10375
10376 memset(buf, 0, sizeof(buf));
10377 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
10378 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
10379
10380 wifi_getApSecurityModeEnabled(vap_index, buf);
10381
10382 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
10383 {
10384 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
10385 return RETURN_ERR;
10386 }
10387 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
10388
10389 memset(buf, 0, sizeof(buf));
10390 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
10391 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);
10392
10393 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
10394 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
10395
10396 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
10397 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
10398
10399 wifi_getApIsolationEnable(vap_index, &enabled);
10400 map->vap_array[i].u.bss_info.isolation = enabled;
10401 }
10402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10403 return RETURN_OK;
10404}
10405
10406INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10407{
10408 unsigned int i;
10409 wifi_vap_info_t *vap_info = NULL;
10410 int acl_mode;
10411 char *sec_str = NULL;
10412
10413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10414 printf("Entering %s index = %d\n", __func__, (int)index);
10415 for (i = 0; i < map->num_vaps; i++)
10416 {
10417 vap_info = &map->vap_array[i];
10418 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
10419
10420 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
10421 else
10422 {
10423 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
10424 else acl_mode = 1;
10425 }
10426 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
10427 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
10428 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
10429
10430 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
10431 if (sec_str)
10432 {
10433 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
10434 }
10435 else
10436 {
10437 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
10438 }
10439
10440 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
10441 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
10442
10443 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
10444 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
10445
10446 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
10447
10448 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
10449 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
10450 }
10451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10452 return RETURN_OK;
10453}
10454
10455int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
10456{
10457 char *token, *next;
10458 const char s[2] = ",";
10459 int count =0;
10460
10461 /* get the first token */
10462 token = strtok_r(pchannels, s, &next);
10463
10464 /* walk through other tokens */
10465 while( token != NULL && count < MAX_CHANNELS) {
10466 chlistptr->channels_list[count++] = atoi(token);
10467 token = strtok_r(NULL, s, &next);
10468 }
10469
10470 return count;
10471}
10472
10473static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
10474{
10475 INT status;
10476 wifi_channels_list_t *chlistp;
10477 CHAR output_string[64];
10478 CHAR pchannels[128];
10479
10480 if(rcap == NULL)
10481 {
10482 return RETURN_ERR;
10483 }
10484
10485 rcap->numSupportedFreqBand = 1;
10486 if (1 == radioIndex)
10487 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
10488 else
10489 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
10490
10491
10492 chlistp = &(rcap->channel_list[0]);
10493 memset(pchannels, 0, sizeof(pchannels));
10494
10495 /* possible number of radio channels */
10496 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
10497 {
10498 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
10499 }
10500 /* Number of channels and list*/
10501 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
10502
10503 /* autoChannelSupported */
10504 /* always ON with wifi_getRadioAutoChannelSupported */
10505 rcap->autoChannelSupported = TRUE;
10506
10507 /* DCSSupported */
10508 /* always ON with wifi_getRadioDCSSupported */
10509 rcap->DCSSupported = TRUE;
10510
10511 /* zeroDFSSupported - TBD */
10512 rcap->zeroDFSSupported = FALSE;
10513
10514 /* Supported Country List*/
10515 memset(output_string, 0, sizeof(output_string));
10516 status = wifi_getRadioCountryCode(radioIndex, output_string);
10517 if( status != 0 ) {
10518 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
10519 return RETURN_ERR;
10520 } else {
10521 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
10522 }
10523 if(!strcmp(output_string,"US")){
10524 rcap->countrySupported[0] = wifi_countrycode_US;
10525 rcap->countrySupported[1] = wifi_countrycode_CA;
10526 } else if (!strcmp(output_string,"CA")) {
10527 rcap->countrySupported[0] = wifi_countrycode_CA;
10528 rcap->countrySupported[1] = wifi_countrycode_US;
10529 } else {
10530 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
10531 }
10532
10533 rcap->numcountrySupported = 2;
10534
10535 /* csi */
10536 rcap->csi.maxDevices = 8;
10537 rcap->csi.soudingFrameSupported = TRUE;
10538
10539 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
10540
10541 /* channelWidth - all supported bandwidths */
10542 int i=0;
10543 rcap->channelWidth[i] = 0;
10544 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
10545 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
10546 WIFI_CHANNELBANDWIDTH_40MHZ);
10547
10548 }
10549 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
10550 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
10551 WIFI_CHANNELBANDWIDTH_40MHZ |
10552 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
10553 }
10554
10555
10556 /* mode - all supported variants */
10557 // rcap->mode[i] = WIFI_80211_VARIANT_H;
10558 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
10559 rcap->mode[i] = (WIFI_80211_VARIANT_N);
10560 }
10561 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
10562 rcap->mode[i] = ( WIFI_80211_VARIANT_AC );
10563 }
10564 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
10565 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
10566
10567 /* supportedBitRate - all supported bitrates */
10568 rcap->supportedBitRate[i] = 0;
10569 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
10570 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
10571 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
10572 }
10573 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
10574 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
10575 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
10576 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
10577 }
10578
10579
10580 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
10581 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
10582 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
10583 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
10584 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
10585 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
10586 rcap->cipherSupported = 0;
10587 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
10588 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
10589
10590 return RETURN_OK;
10591}
10592
10593INT wifi_getHalCapability(wifi_hal_capability_t *cap)
10594{
10595 INT status, radioIndex;
10596 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
10597 int iter = 0;
10598 unsigned int j;
10599 wifi_interface_name_idex_map_t *iface_info;
10600
10601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10602
10603 memset(cap, 0, sizeof(wifi_hal_capability_t));
10604
10605 /* version */
10606 cap->version.major = WIFI_HAL_MAJOR_VERSION;
10607 cap->version.minor = WIFI_HAL_MINOR_VERSION;
10608
10609 /* number of radios platform property */
10610 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
10611 _syscmd(cmd, output, sizeof(output));
10612 cap->wifi_prop.numRadios = atoi(output);
10613
10614 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
10615 {
10616 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
10617 if (status != 0) {
10618 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
10619 return RETURN_ERR;
10620 }
10621
10622 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
10623 {
10624 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
10625 {
10626 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
10627 return RETURN_ERR;
10628 }
10629 iface_info = &cap->wifi_prop.interface_map[iter];
10630 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
10631 iface_info->rdk_radio_index = radioIndex;
10632 memset(output, 0, sizeof(output));
10633 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
10634 {
10635 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
10636 }
10637 // TODO: bridge name
10638 // TODO: vlan id
10639 // TODO: primary
10640 iface_info->index = array_index_to_vap_index(radioIndex, j);
10641 memset(output, 0, sizeof(output));
10642 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
10643 {
10644 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
10645 }
10646 iter++;
10647 }
10648 }
10649
10650 cap->BandSteeringSupported = FALSE;
10651 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10652 return RETURN_OK;
10653}
10654
10655INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
10656{
10657 //TODO
10658 return RETURN_OK;
10659}
10660
10661INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
10662{
10663 //TODO
10664 return RETURN_OK;
10665}
10666
10667#endif /* WIFI_HAL_VERSION_3 */
10668
10669#ifdef WIFI_HAL_VERSION_3_PHASE2
10670INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
10671{
10672 return RETURN_OK;
10673}
10674#else
10675INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
10676{
10677 char cmd[128];
10678 BOOL status = false;
10679
10680 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
10681 return RETURN_ERR;
10682
10683 output_buf[0] = '\0';
10684
10685 wifi_getApEnable(ap_index,&status);
10686 if (!status)
10687 return RETURN_OK;
10688
10689 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
10690 _syscmd(cmd, output_buf, output_buf_size);
10691
10692 return RETURN_OK;
10693}
10694#endif
developer2f513ab2022-09-13 14:26:06 +080010695
10696INT wifi_getProxyArp(INT apIndex, BOOL *enable)
10697{
10698 char output[16]={'\0'};
10699 char config_file[MAX_BUF_SIZE] = {0};
10700
10701 if (!enable)
10702 return RETURN_ERR;
10703
10704 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
10705 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
10706
10707 if (strlen(output) == 0)
10708 *enable = FALSE;
10709 else if (strncmp(output, "1", 1) == 0)
10710 *enable = TRUE;
10711 else
10712 *enable = FALSE;
10713
10714 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
10715 return RETURN_OK;
10716}
developer2d9c30f2022-09-13 15:06:14 +080010717
10718INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
10719{
10720 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
10721 return RETURN_ERR;
10722 *output_enable=TRUE;
10723 return RETURN_OK;
10724}