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