blob: 7976c60e8a997b51fc97ac49740480ea6cd1b8e2 [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"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer454b9462022-09-13 15:29:16 +080082
developer06a01d92022-09-07 16:32:39 +080083#define DRIVER_2GHZ "ath9k"
84#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080085#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080086
87/*
88 MAX_APS - Number of all AP available in system
89 2x Home AP
90 2x Backhaul AP
91 2x Guest AP
92 2x Secure Onboard AP
93 2x Service AP
94
95*/
96#define MAX_APS 10
97#define NUMBER_OF_RADIOS 2
98
99#ifndef AP_PREFIX
100#define AP_PREFIX "wifi"
101#endif
102
103#ifndef RADIO_PREFIX
104#define RADIO_PREFIX "wlan"
105#endif
106
107#define MAX_BUF_SIZE 128
108#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800109#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800110
111//Uncomment to enable debug logs
112//#define WIFI_DEBUG
113
114#ifdef WIFI_DEBUG
115#define wifi_dbg_printf printf
116#define WIFI_ENTRY_EXIT_DEBUG printf
117#else
118#define wifi_dbg_printf(format, args...) printf("")
119#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
120#endif
121
122#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
123#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
124#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
125#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
126#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
127#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
128#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
129#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
130#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
131#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
132
133#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
134#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
135
136#define BW_FNAME "/nvram/bw_file.txt"
137
138#define PS_MAX_TID 16
139
140static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
141 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
142 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
143 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
145 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
146 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
147 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
148 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
149 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
150 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
151 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
153 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
154 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
155 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
156 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
157};
158
159typedef unsigned long long u64;
160
161/* Enum to define WiFi Bands */
162typedef enum
163{
164 band_invalid = -1,
165 band_2_4 = 0,
166 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800167 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800168} wifi_band;
169
developerdb744382022-09-13 15:34:54 +0800170typedef enum {
171 WIFI_MODE_A = 0x01,
172 WIFI_MODE_B = 0x02,
173 WIFI_MODE_G = 0x04,
174 WIFI_MODE_N = 0x08,
175 WIFI_MODE_AC = 0x10,
176 WIFI_MODE_AX = 0x20,
177} wifi_ieee80211_Mode;
178
developer06a01d92022-09-07 16:32:39 +0800179#ifdef WIFI_HAL_VERSION_3
180
181// Return number of elements in array
182#ifndef ARRAY_SIZE
183#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
184#endif /* ARRAY_SIZE */
185
186#ifndef ARRAY_AND_SIZE
187#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
188#endif /* ARRAY_AND_SIZE */
189
190#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
191
192typedef struct {
193 int32_t value;
194 int32_t param;
195 intptr_t key;
196 intptr_t data;
197} wifi_secur_list;
198
199wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
200wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
201char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
202
203static wifi_secur_list map_security[] =
204{
205 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
206 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
214};
215
216wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
217{
218 wifi_secur_list *item;
219 int i;
220
221 for (item = list,i = 0;i < list_sz; item++, i++) {
222 if ((int)(item->key) == key) {
223 return item;
224 }
225 }
226
227 return NULL;
228}
229
230char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
231{
232 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
233
234 if (!item) {
235 return "";
236 }
237
238 return (char *)(item->data);
239}
240
241wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
242{
243 wifi_secur_list *item;
244 int i;
245
246 for (item = list,i = 0;i < list_sz; item++, i++) {
247 if (strcmp((char *)(item->data), str) == 0) {
248 return item;
249 }
250 }
251
252 return NULL;
253}
254#endif /* WIFI_HAL_VERSION_3 */
255
256#ifdef HAL_NETLINK_IMPL
257typedef struct {
258 int id;
259 struct nl_sock* socket;
260 struct nl_cb* cb;
261} Netlink;
262
263static int mac_addr_aton(unsigned char *mac_addr, char *arg)
264{
265 unsigned int mac_addr_int[6]={};
266 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);
267 mac_addr[0] = mac_addr_int[0];
268 mac_addr[1] = mac_addr_int[1];
269 mac_addr[2] = mac_addr_int[2];
270 mac_addr[3] = mac_addr_int[3];
271 mac_addr[4] = mac_addr_int[4];
272 mac_addr[5] = mac_addr_int[5];
273 return 0;
274}
275
276static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
277{
278 unsigned int mac_addr_int[6]={};
279 mac_addr_int[0] = arg[0];
280 mac_addr_int[1] = arg[1];
281 mac_addr_int[2] = arg[2];
282 mac_addr_int[3] = arg[3];
283 mac_addr_int[4] = arg[4];
284 mac_addr_int[5] = arg[5];
285 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]);
286 return;
287}
288
289static int ieee80211_frequency_to_channel(int freq)
290{
291 if (freq == 2484)
292 return 14;
293 else if (freq < 2484)
294 return (freq - 2407) / 5;
295 else if (freq >= 4910 && freq <= 4980)
296 return (freq - 4000) / 5;
297 else if (freq <= 45000)
298 return (freq - 5000) / 5;
299 else if (freq >= 58320 && freq <= 64800)
300 return (freq - 56160) / 2160;
301 else
302 return 0;
303}
304
305static int initSock80211(Netlink* nl) {
306 nl->socket = nl_socket_alloc();
307 if (!nl->socket) {
308 fprintf(stderr, "Failing to allocate the sock\n");
309 return -ENOMEM;
310 }
311
312 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
313
314 if (genl_connect(nl->socket)) {
315 fprintf(stderr, "Failed to connect\n");
316 nl_close(nl->socket);
317 nl_socket_free(nl->socket);
318 return -ENOLINK;
319 }
320
321 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
322 if (nl->id< 0) {
323 fprintf(stderr, "interface not found.\n");
324 nl_close(nl->socket);
325 nl_socket_free(nl->socket);
326 return -ENOENT;
327 }
328
329 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
330 if ((!nl->cb)) {
331 fprintf(stderr, "Failed to allocate netlink callback.\n");
332 nl_close(nl->socket);
333 nl_socket_free(nl->socket);
334 return ENOMEM;
335 }
336
337 return nl->id;
338}
339
340static int nlfree(Netlink *nl)
341{
342 nl_cb_put(nl->cb);
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return 0;
346}
347
348static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
349 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
350 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
351 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
352};
353
354static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
355};
356
357static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
358};
359
360typedef struct _wifi_channelStats_loc {
361 INT array_size;
362 INT ch_number;
363 BOOL ch_in_pool;
364 INT ch_noise;
365 BOOL ch_radar_noise;
366 INT ch_max_80211_rssi;
367 INT ch_non_80211_noise;
368 INT ch_utilization;
369 ULLONG ch_utilization_total;
370 ULLONG ch_utilization_busy;
371 ULLONG ch_utilization_busy_tx;
372 ULLONG ch_utilization_busy_rx;
373 ULLONG ch_utilization_busy_self;
374 ULLONG ch_utilization_busy_ext;
375} wifi_channelStats_t_loc;
376
377typedef struct wifi_device_info {
378 INT wifi_devIndex;
379 UCHAR wifi_devMacAddress[6];
380 CHAR wifi_devIPAddress[64];
381 BOOL wifi_devAssociatedDeviceAuthentiationState;
382 INT wifi_devSignalStrength;
383 INT wifi_devTxRate;
384 INT wifi_devRxRate;
385} wifi_device_info_t;
386
387#endif
388
389//For 5g Alias Interfaces
390static BOOL priv_flag = TRUE;
391static BOOL pub_flag = TRUE;
392static BOOL Radio_flag = TRUE;
393//wifi_setApBeaconRate(1, beaconRate);
394
395struct params
396{
397 char * name;
398 char * value;
399};
400
401static int _syscmd(char *cmd, char *retBuf, int retBufSize)
402{
403 FILE *f;
404 char *ptr = retBuf;
405 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
406
407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
408 if((f = popen(cmd, "r")) == NULL) {
409 fprintf(stderr,"\npopen %s error\n", cmd);
410 return RETURN_ERR;
411 }
412
413 while(!feof(f))
414 {
415 *ptr = 0;
416 if(bufSize>=128) {
417 bufbytes=128;
418 } else {
419 bufbytes=bufSize-1;
420 }
421
422 fgets(ptr,bufbytes,f);
423 readbytes=strlen(ptr);
424
425 if(!readbytes)
426 break;
427
428 bufSize-=readbytes;
429 ptr += readbytes;
430 }
431 cmd_ret = pclose(f);
432 retBuf[retBufSize-1]=0;
433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
434
435 return cmd_ret >> 8;
436}
437
developerc707e972022-09-13 15:38:02 +0800438wifi_band wifi_index_to_band(int apIndex)
439{
440 char cmd[128] = {0};
441 char buf[64] = {0};
442 int freq = 0;
443 wifi_band band = band_invalid;
444
445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
446 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
447 _syscmd(cmd, buf, sizeof(buf));
448 freq = strtol(buf, NULL, 10);
449 if (freq > 2401 && freq < 2495)
450 band = band_2_4;
451 else if (freq > 5160 && freq < 5915)
452 band = band_5;
453 else if (freq > 5955 && freq < 7125)
454 band = band_6;
455
456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
457 return band;
458}
459
developer06a01d92022-09-07 16:32:39 +0800460static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
461{
462 char cmd[MAX_CMD_SIZE]={'\0'};
463 char buf[MAX_BUF_SIZE]={'\0'};
464 int ret = 0;
465
466 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
467 ret = _syscmd(cmd, buf, sizeof(buf));
468 if ((ret != 0) && (strlen(buf) == 0))
469 return -1;
470 snprintf(output, output_size, "%s", buf);
471
472 return 0;
473}
474
475static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
476{
477 char cmd[MAX_CMD_SIZE]={'\0'};
478 char buf[MAX_BUF_SIZE]={'\0'};
479
480 for(int i=0;i<item_count;i++)
481 {
482 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
483 if (strlen(buf) == 0) //Insert
484 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
485 else //Update
486 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
487 if(_syscmd(cmd, buf, sizeof(buf)))
488 return -1;
489 }
490
491 return 0;
492}
493
494static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
495{
496 char cmd[MAX_CMD_SIZE]="", output[32]="";
497 FILE *fp;
498 int i;
499 //NOTE RELOAD should be done in ApplySSIDSettings
500
501 for(i=0; i<item_count; i++, list++)
502 {
503 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
504 if((fp = popen(cmd, "r"))==NULL)
505 {
506 perror("popen failed");
507 return -1;
508 }
509 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
510 {
511 pclose(fp);
512 perror("fgets failed");
513 return -1;
514 }
515 pclose(fp);
516 }
517 return 0;
518}
519
520static int wifi_reloadAp(int apIndex)
521{
522 char cmd[MAX_CMD_SIZE]="";
523 char buf[MAX_BUF_SIZE]="";
524
525 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", 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 disable", AP_PREFIX, apIndex);
530 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
531 return RETURN_ERR;
532
533 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
534 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
535 return RETURN_ERR;
536
537 return RETURN_OK;
538}
539
540
541//For Getting Current Interface Name from corresponding hostapd configuration
542void GetInterfaceName(char *interface_name, char *conf_file)
543{
544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
545 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
547}
548
549INT File_Reading(CHAR *file, char *Value)
550{
551 FILE *fp = NULL;
552 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
553 int count = 0;
554
555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
556 fp = popen(file,"r");
557 if(fp == NULL)
558 return RETURN_ERR;
559
560 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
561 {
562 for(count=0;buf[count]!='\n';count++)
563 copy_buf[count]=buf[count];
564 copy_buf[count]='\0';
565 }
566 strcpy(Value,copy_buf);
567 pclose(fp);
568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
569
570 return RETURN_OK;
571}
572
573void wifi_RestartHostapd_2G()
574{
575 int Public2GApIndex = 4;
576
577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
578 wifi_setApEnable(Public2GApIndex, FALSE);
579 wifi_setApEnable(Public2GApIndex, TRUE);
580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
581}
582
583void wifi_RestartHostapd_5G()
584{
585 int Public5GApIndex = 5;
586
587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
588 wifi_setApEnable(Public5GApIndex, FALSE);
589 wifi_setApEnable(Public5GApIndex, TRUE);
590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
591}
592
593void wifi_RestartPrivateWifi_2G()
594{
595 int PrivateApIndex = 0;
596
597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
598 wifi_setApEnable(PrivateApIndex, FALSE);
599 wifi_setApEnable(PrivateApIndex, TRUE);
600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
601}
602
603void wifi_RestartPrivateWifi_5G()
604{
605 int Private5GApIndex = 1;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(Private5GApIndex, FALSE);
609 wifi_setApEnable(Private5GApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613static int writeBandWidth(int radioIndex,char *bw_value)
614{
615 char buf[MAX_BUF_SIZE];
616 char cmd[MAX_CMD_SIZE];
617
618 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
619 if(_syscmd(cmd, buf, sizeof(buf)))
620 {
621 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
622 _syscmd(cmd, buf, sizeof(buf));
623 return RETURN_OK;
624 }
625
626 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
627 _syscmd(cmd,buf,sizeof(buf));
628 return RETURN_OK;
629}
630
631static int readBandWidth(int radioIndex,char *bw_value)
632{
633 char buf[MAX_BUF_SIZE];
634 char cmd[MAX_CMD_SIZE];
635 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
636 _syscmd(cmd,buf,sizeof(buf));
637 if(NULL!=strstr(buf,"20MHz"))
638 {
639 strcpy(bw_value,"20MHz");
640 }
641 else if(NULL!=strstr(buf,"40MHz"))
642 {
643 strcpy(bw_value,"40MHz");
644 }
645 else if(NULL!=strstr(buf,"80MHz"))
646 {
647 strcpy(bw_value,"80MHz");
648 }
649 else
650 {
651 return RETURN_ERR;
652 }
653 return RETURN_OK;
654}
655
developer5f222492022-09-13 15:21:52 +0800656// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800657INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
658{
developer5f222492022-09-13 15:21:52 +0800659 struct params params={'\0'};
660 char config_file[MAX_BUF_SIZE] = {0};
661 char buf[MAX_BUF_SIZE] = {'\0'};
662
663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
664 if (strlen (beaconRate) < 5)
665 return RETURN_ERR;
666 // Copy the numeric value
667 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
668 buf[strlen(beaconRate) - 4] = '\0';
669
670 params.name = "beacon_rate";
671 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
672 if (strncmp(buf, "5.5", 3) == 0) {
673 snprintf(buf, sizeof(buf), "55");
674 params.value = buf;
675 } else {
676 strcat(buf, "0");
677 params.value = buf;
678 }
679
680 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
681 wifi_hostapdWrite(config_file, &params, 1);
682 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
684
685 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800686}
687
688INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
689{
developer5f222492022-09-13 15:21:52 +0800690 char config_file[MAX_BUF_SIZE] = {'\0'};
691 char temp_output[MAX_BUF_SIZE] = {'\0'};
692 char buf[MAX_BUF_SIZE] = {'\0'};
693 float rate = 0;
694
695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
696 if (NULL == beaconRate)
697 return RETURN_ERR;
698
699 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
700 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
701 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
702 if(strlen(buf) > 0) {
703 rate = atof(buf)/10;
704 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
705 } else {
706 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
707 }
708 strncpy(beaconRate, temp_output, sizeof(temp_output));
709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
710
711 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800712}
713
714INT wifi_setLED(INT radioIndex, BOOL enable)
715{
716 return 0;
717}
718INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
719{
720 return RETURN_OK;
721}
722/**********************************************************************************
723 *
724 * Wifi Subsystem level function prototypes
725 *
726**********************************************************************************/
727//---------------------------------------------------------------------------------------------------
728//Wifi system api
729//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
730INT wifi_getHalVersion(CHAR *output_string) //RDKB
731{
732 if(!output_string)
733 return RETURN_ERR;
734 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
735
736 return RETURN_OK;
737}
738
739
740/* wifi_factoryReset() function */
741/**
742* @description Clears internal variables to implement a factory reset of the Wi-Fi
743* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
744*
745* @param None
746*
747* @return The status of the operation.
748* @retval RETURN_OK if successful.
749* @retval RETURN_ERR if any error is detected
750*
751* @execution Synchronous
752* @sideeffect None
753*
754* @note This function must not suspend and must not invoke any blocking system
755* calls. It should probably just send a message to a driver event handler task.
756*
757*/
758INT wifi_factoryReset()
759{
760 char cmd[128];
761
762 /*delete running hostapd conf files*/
763 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
764 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
765 system(cmd);
766 system("systemctl restart hostapd.service");
767
768 return RETURN_OK;
769}
770
771/* wifi_factoryResetRadios() function */
772/**
773* @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.
774*
775* @param None
776* @return The status of the operation
777* @retval RETURN_OK if successful
778* @retval RETURN_ERR if any error is detected
779*
780* @execution Synchronous
781*
782* @sideeffect None
783*
784* @note This function must not suspend and must not invoke any blocking system
785* calls. It should probably just send a message to a driver event handler task.
786*
787*/
788INT wifi_factoryResetRadios()
789{
790 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
791 return RETURN_OK;
792
793 return RETURN_ERR;
794}
795
796
797/* wifi_factoryResetRadio() function */
798/**
799* @description Restore selected radio parameters without touching access point parameters
800*
801* @param radioIndex - Index of Wi-Fi Radio channel
802*
803* @return The status of the operation.
804* @retval RETURN_OK if successful.
805* @retval RETURN_ERR if any error is detected
806*
807* @execution Synchronous.
808* @sideeffect None.
809*
810* @note This function must not suspend and must not invoke any blocking system
811* calls. It should probably just send a message to a driver event handler task.
812*
813*/
814INT wifi_factoryResetRadio(int radioIndex) //RDKB
815{
developer5ff7f5f2022-09-13 15:12:16 +0800816 system("systemctl stop hostapd.service");
817
developer06a01d92022-09-07 16:32:39 +0800818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
819 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800820 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800821 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800822 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800823 else
824 return RETURN_ERR;
825
developer5ff7f5f2022-09-13 15:12:16 +0800826 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
828 return RETURN_OK;
829}
830
831/* wifi_initRadio() function */
832/**
833* Description: This function call initializes the specified radio.
834* Implementation specifics may dictate the functionality since
835* different hardware implementations may have different initilization requirements.
836* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
837*
838* @return The status of the operation.
839* @retval RETURN_OK if successful.
840* @retval RETURN_ERR if any error is detected
841*
842* @execution Synchronous.
843* @sideeffect None.
844*
845* @note This function must not suspend and must not invoke any blocking system
846* calls. It should probably just send a message to a driver event handler task.
847*
848*/
849INT wifi_initRadio(INT radioIndex)
850{
851 //TODO: Initializes the wifi subsystem (for specified radio)
852 return RETURN_OK;
853}
854void macfilter_init()
855{
856 char count[4]={'\0'};
857 char buf[253]={'\0'};
858 char tmp[19]={'\0'};
859 int dev_count,block,mac_entry=0;
860 char res[4]={'\0'};
861 char acl_file_path[64] = {'\0'};
862 FILE *fp = NULL;
863 int index=0;
864 char iface[10]={'\0'};
865 char config_file[MAX_BUF_SIZE] = {0};
866
867
868 sprintf(acl_file_path,"/tmp/mac_filter.sh");
869
870 fp=fopen(acl_file_path,"w+");
871 sprintf(buf,"#!/bin/sh \n");
872 fprintf(fp,"%s\n",buf);
873
874 system("chmod 0777 /tmp/mac_filter.sh");
875
876 for(index=0;index<=1;index++)
877 {
878 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
879 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
880 sprintf(buf,"syscfg get %dcountfilter",index);
881 _syscmd(buf,count,sizeof(count));
882 mac_entry=atoi(count);
883
884 sprintf(buf,"syscfg get %dblockall",index);
885 _syscmd(buf,res,sizeof(res));
886 block = atoi(res);
887
888 //Allow only those macs mentioned in ACL
889 if(block==1)
890 {
891 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
892 fprintf(fp,"%s\n",buf);
893 for(dev_count=1;dev_count<=mac_entry;dev_count++)
894 {
895 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
896 _syscmd(buf,tmp,sizeof(tmp));
897 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
898 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
899 fprintf(fp,"%s\n",buf);
900 }
901 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
902 fprintf(fp,"%s\n",buf);
903 }
904
905 //Block all the macs mentioned in ACL
906 else if(block==2)
907 {
908 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
909 fprintf(fp,"%s\n",buf);
910
911 for(dev_count=1;dev_count<=mac_entry;dev_count++)
912 {
913 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
914 _syscmd(buf,tmp,sizeof(tmp));
915 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
916 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
917 fprintf(fp,"%s\n",buf);
918 }
919 }
920 }
921 fclose(fp);
922}
923
924// Initializes the wifi subsystem (all radios)
925INT wifi_init() //RDKB
926{
927 char interface[MAX_BUF_SIZE]={'\0'};
928 char bridge_name[MAX_BUF_SIZE]={'\0'};
929 INT len=0;
930
931 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
932 //Not intitializing macfilter for Turris-Omnia Platform for now
933 //macfilter_init();
934
935 system("/usr/sbin/iw reg set US");
936 system("systemctl start hostapd.service");
937 sleep(2);//sleep to wait for hostapd to start
938
939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
940
941 return RETURN_OK;
942}
943
944/* wifi_reset() function */
945/**
946* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
947* Implementation specifics may dictate what is actualy reset since
948* different hardware implementations may have different requirements.
949* Parameters : None
950*
951* @return The status of the operation.
952* @retval RETURN_OK if successful.
953* @retval RETURN_ERR if any error is detected
954*
955* @execution Synchronous.
956* @sideeffect None.
957*
958* @note This function must not suspend and must not invoke any blocking system
959* calls. It should probably just send a message to a driver event handler task.
960*
961*/
962INT wifi_reset()
963{
964 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800965 system("systemctl stop hostapd.service");
966 sleep(2);
967 system("systemctl start hostapd.service");
968 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800969 return RETURN_OK;
970}
971
972/* wifi_down() function */
973/**
974* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
975* Implementation specifics may dictate some functionality since
976* different hardware implementations may have different requirements.
977*
978* @param None
979*
980* @return The status of the operation
981* @retval RETURN_OK if successful
982* @retval RETURN_ERR if any error is detected
983*
984* @execution Synchronous
985* @sideeffect None
986*
987* @note This function must not suspend and must not invoke any blocking system
988* calls. It should probably just send a message to a driver event handler task.
989*
990*/
991INT wifi_down()
992{
993 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +0800994 system("systemctl stop hostapd.service");
995 sleep(2);
developer06a01d92022-09-07 16:32:39 +0800996 return RETURN_OK;
997}
998
999
1000/* wifi_createInitialConfigFiles() function */
1001/**
1002* @description This function creates wifi configuration files. The format
1003* and content of these files are implementation dependent. This function call is
1004* used to trigger this task if necessary. Some implementations may not need this
1005* function. If an implementation does not need to create config files the function call can
1006* do nothing and return RETURN_OK.
1007*
1008* @param None
1009*
1010* @return The status of the operation
1011* @retval RETURN_OK if successful
1012* @retval RETURN_ERR if any error is detected
1013*
1014* @execution Synchronous
1015* @sideeffect None
1016*
1017* @note This function must not suspend and must not invoke any blocking system
1018* calls. It should probably just send a message to a driver event handler task.
1019*
1020*/
1021INT wifi_createInitialConfigFiles()
1022{
1023 //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)
1024 return RETURN_OK;
1025}
1026
1027// outputs the country code to a max 64 character string
1028INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1029{
developer7543b3b2022-09-13 13:47:17 +08001030 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1031 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001032 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001033
1034 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1035 _syscmd(cmd, buf, sizeof(buf));
1036 if(strlen(buf) > 0)
1037 snprintf(output_string, 64, "%s", buf);
1038 else
1039 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001040
1041 return RETURN_OK;
1042}
1043
1044INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1045{
1046 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001047 char str[MAX_BUF_SIZE]={'\0'};
1048 char cmd[MAX_CMD_SIZE]={'\0'};
1049 struct params params;
1050 char config_file[MAX_BUF_SIZE] = {0};
1051
1052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1053 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1054 return RETURN_ERR;
1055
1056 params.name = "country_code";
1057 params.value = CountryCode;
1058 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1059 int ret = wifi_hostapdWrite(config_file, &params, 1);
1060 if (ret) {
1061 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1062 ,__func__, ret);
1063 }
1064
1065 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1066 if (ret) {
1067 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1068 ,__func__, ret);
1069 }
1070 wifi_reloadAp(radioIndex);
1071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1072
developer06a01d92022-09-07 16:32:39 +08001073 return RETURN_OK;
1074}
1075
developera748dcf2022-09-13 15:56:48 +08001076INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1077{
1078 char channel_util_file[64] = {0};
1079 char cmd[128] = {0};
1080 char buf[128] = {0};
1081 char line[128] = {0};
1082 char *param = NULL, *value = NULL;
1083 int read = 0;
1084 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1085 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1086 size_t len = 0;
1087 FILE *f = NULL;
1088
1089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1090
1091 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1092 _syscmd(cmd, buf, sizeof(buf));
1093 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1094
1095 memset(cmd, 0, sizeof(cmd));
1096 memset(buf, 0, sizeof(buf));
1097 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1098 if ((f = popen(cmd, "r")) == NULL) {
1099 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1100 return RETURN_ERR;
1101 }
1102
1103 read = getline(&line, &len, f);
1104 while (read != -1) {
1105 param = strtok(line, ":\t");
1106 value = strtok(NULL, " ");
1107 if(strstr(param, "frequency") != NULL) {
1108 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1109 }
1110 if(strstr(param, "noise") != NULL) {
1111 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1112 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1113 }
1114 if(strstr(param, "channel active time") != NULL) {
1115 ActiveTime = strtol(value, NULL, 10);
1116 }
1117 if(strstr(param, "channel busy time") != NULL) {
1118 BusyTime = strtol(value, NULL, 10);
1119 }
1120 if(strstr(param, "channel transmit time") != NULL) {
1121 TransmitTime = strtol(value, NULL, 10);
1122 }
1123 read = getline(&line, &len, f);
1124 }
1125 pclose(f);
1126
1127 // The file should store the last active, busy and transmit time
1128 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1129 f = fopen(channel_util_file, "r");
1130 if (f != NULL) {
1131 read = getline(&line, &len, f);
1132 preActiveTime = strtol(line, NULL, 10);
1133 read = getline(&line, &len, f);
1134 preBusyTime = strtol(line, NULL, 10);
1135 read = getline(&line, &len, f);
1136 preTransmitTime = strtol(line, NULL, 10);
1137 fclose(f);
1138 }
1139
1140 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1141 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1142
1143 f = fopen(channel_util_file, "w");
1144 if (f != NULL) {
1145 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1146 fclose(f);
1147 }
1148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1149 return RETURN_OK;
1150}
1151
developer06a01d92022-09-07 16:32:39 +08001152/**********************************************************************************
1153 *
1154 * Wifi radio level function prototypes
1155 *
1156**********************************************************************************/
1157
1158//Get the total number of radios in this wifi subsystem
1159INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1160{
1161 if (NULL == output)
1162 return RETURN_ERR;
1163 *output = 2;
1164
1165 return RETURN_OK;
1166}
1167
1168//Get the total number of SSID entries in this wifi subsystem
1169INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1170{
1171 if (NULL == output)
1172 return RETURN_ERR;
1173 *output = MAX_APS;
1174
1175 return RETURN_OK;
1176}
1177
1178//Get the Radio enable config parameter
1179INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1180{
1181 char interface_path[MAX_CMD_SIZE] = {0};
1182 FILE *fp = NULL;
1183
1184 if (NULL == output_bool)
1185 return RETURN_ERR;
1186
1187 *output_bool = FALSE;
1188 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1189 return RETURN_ERR;
1190
1191 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1192 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001193 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001194 {
developercf48e482022-09-13 14:49:50 +08001195 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001196 }
1197 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001198 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1199 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1200 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001201
developercf48e482022-09-13 14:49:50 +08001202 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1203 *output_bool = TRUE;
1204 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001205 return RETURN_OK;
1206}
1207
1208INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1209{
1210 char cmd[MAX_CMD_SIZE] = {0};
1211 char buf[MAX_CMD_SIZE] = {0};
1212 int apIndex, ret;
1213 FILE *fp = NULL;
1214
1215 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1216 if(enable==FALSE)
1217 {
1218 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1219 {
1220 //Detaching %s%d from hostapd daemon
1221 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1222 _syscmd(cmd, buf, sizeof(buf));
1223 if(strncmp(buf, "OK", 2))
1224 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1225 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1226 _syscmd(cmd, buf, sizeof(buf));
1227 }
developer456aa3e2022-09-13 14:27:36 +08001228 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001229 _syscmd(cmd, buf, sizeof(buf));
1230 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001231 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001232 }
1233 else
1234 {
developer456aa3e2022-09-13 14:27:36 +08001235 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001236 _syscmd(cmd, buf, sizeof(buf));
1237 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001238 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001239 sleep(1);
1240 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1241 {
1242 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1243 fp = fopen(cmd, "r");
1244 if(!fp)
1245 {
1246 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1247 _syscmd(cmd, buf, sizeof(buf));
1248 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1249 _syscmd(cmd, buf, sizeof(buf));
1250 }
1251 if(fp)
1252 fclose(fp);
1253 }
1254 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1255 {
1256 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1257 ret = _syscmd(cmd, buf, sizeof(buf));
1258 if ( ret == RETURN_ERR)
1259 {
1260 fprintf(stderr, "VAP interface creation failed\n");
1261 continue;
1262 }
1263 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1264 _syscmd(cmd, buf, sizeof(buf));
1265 if(*buf == '1')
1266 {
1267 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1268 radioIndex, apIndex);
1269 _syscmd(cmd, buf, sizeof(buf));
1270 if(strncmp(buf, "OK", 2))
1271 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1272 }
1273 }
1274 }
1275
1276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1277 return RETURN_OK;
1278}
1279
1280//Get the Radio enable status
1281INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1282{
1283 if (NULL == output_bool)
1284 return RETURN_ERR;
1285
1286 return wifi_getRadioEnable(radioIndex, output_bool);
1287}
1288
1289//Get the Radio Interface name from platform, eg "wlan0"
1290INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1291{
1292 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1293 return RETURN_ERR;
1294 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1295
1296 return RETURN_OK;
1297}
1298
1299//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1300//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.
1301INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1302{
1303 char cmd[1024] = {0};
1304 char buf[1024] = {0};
1305 char HConf_file[MAX_BUF_SIZE] = {'\0'};
1306 char interface_name[50] = {0};
1307
1308 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1309 if (NULL == output_string)
1310 return RETURN_ERR;
1311
1312 sprintf(HConf_file,"%s%d%s","/nvram/hostapd",radioIndex,".conf");
1313 GetInterfaceName(interface_name,HConf_file);
1314
1315 sprintf(cmd, "iwconfig %s | grep 'Bit Rate' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1,2", interface_name);
1316 _syscmd(cmd, buf, sizeof(buf));
1317
1318 if(strlen(buf) > 0)
1319 snprintf(output_string, 64, "%s", buf);
1320 else
1321 {
1322 wifi_getRadioOperatingChannelBandwidth(radioIndex,buf);
1323 if((strcmp(buf,"20MHz") == 0) && (radioIndex == 0))
1324 strcpy(output_string,"144 Mb/s");
1325 else if((strcmp(buf,"20MHz") == 0) && (radioIndex == 1))
1326 strcpy(output_string,"54 Mb/s");
1327 else if((strcmp(buf,"40MHz") == 0) && (radioIndex == 1))
1328 strcpy(output_string,"300 Mb/s");
1329 //TODO: CHECK VALID VALUE
1330 }
1331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1332
1333 return RETURN_OK;
1334}
1335#if 0
1336INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1337{
1338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1339 char cmd[64];
1340 char buf[1024];
1341 int apIndex;
1342
1343 if (NULL == output_string)
1344 return RETURN_ERR;
1345
1346 apIndex=(radioIndex==0)?0:1;
1347
1348 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1349 _syscmd(cmd,buf, sizeof(buf));
1350
1351 snprintf(output_string, 64, "%s", buf);
1352 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1353 return RETURN_OK;
1354}
1355#endif
1356
1357
1358//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1359//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.
1360INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1361{
developer963da0c2022-09-13 15:58:27 +08001362 wifi_band band = band_invalid;
1363
developer06a01d92022-09-07 16:32:39 +08001364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1365 if (NULL == output_string)
1366 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001367
1368 band = wifi_index_to_band(radioIndex);
1369
1370 memset(output_string, 0, 10);
1371 if (band == band_2_4)
1372 strcpy(output_string, "2.4GHz");
1373 else if (band == band_5)
1374 strcpy(output_string, "5GHz");
1375 else if (band == band_6)
1376 strcpy(output_string, "6GHz");
1377 else
1378 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001379 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1380
1381 return RETURN_OK;
1382#if 0
1383 char buf[MAX_BUF_SIZE]={'\0'};
1384 char str[MAX_BUF_SIZE]={'\0'};
1385 char cmd[MAX_CMD_SIZE]={'\0'};
1386 char *ch=NULL;
1387 char *ch2=NULL;
1388
1389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1390 if (NULL == output_string)
1391 return RETURN_ERR;
1392
1393
1394 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1395
1396 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1397 {
1398 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1399 return RETURN_ERR;
1400 }
1401 ch=strchr(buf,'\n');
1402 *ch='\0';
1403 ch=strchr(buf,'=');
1404 if(ch==NULL)
1405 return RETURN_ERR;
1406
1407
1408 ch++;
1409
1410 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1411 strcpy(buf,"0");
1412 if(strlen(ch) == 1)
1413 ch=strcat(buf,ch);
1414
1415
1416 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1417
1418 if(_syscmd(cmd,str,64) == RETURN_ERR)
1419 {
1420 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1421 return RETURN_ERR;
1422 }
1423
1424
1425 ch2=strchr(str,'\n');
1426 //replace \n with \0
1427 *ch2='\0';
1428 ch2=strchr(str,'=');
1429 if(ch2==NULL)
1430 {
1431 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1432 return RETURN_ERR;
1433 }
1434 else
1435 wifi_dbg_printf("%s",ch2+1);
1436
1437
1438 ch2++;
1439
1440
1441 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1442
1443 memset(buf,'\0',sizeof(buf));
1444 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1445 {
1446 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1447 return RETURN_ERR;
1448 }
1449 if (strstr(buf,"2.4") != NULL )
1450 strcpy(output_string,"2.4GHz");
1451 else if(strstr(buf,"5.") != NULL )
1452 strcpy(output_string,"5GHz");
1453 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1454
1455 return RETURN_OK;
1456#endif
1457}
1458
1459//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1460//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.
1461INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1462{
1463 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1464 if (NULL == output_string)
1465 return RETURN_ERR;
1466 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1468
1469 return RETURN_OK;
1470#if 0
1471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1472 char buf[MAX_BUF_SIZE]={'\0'};
1473 char str[MAX_BUF_SIZE]={'\0'};
1474 char cmd[MAX_CMD_SIZE]={'\0'};
1475 char *ch=NULL;
1476 char *ch2=NULL;
1477 char ch1[5]="0";
1478
1479 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1480
1481 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1482 {
1483 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1484 return RETURN_ERR;
1485 }
1486
1487 ch=strchr(buf,'\n');
1488 *ch='\0';
1489 ch=strchr(buf,'=');
1490 if(ch==NULL)
1491 return RETURN_ERR;
1492 ch++;
1493
1494 if(strlen(ch)==1)
1495 {
1496 strcat(ch1,ch);
1497
1498 }
1499 else
1500 {
1501 strcpy(ch1,ch);
1502 }
1503
1504
1505
1506 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1507 if(_syscmd(cmd,str,64) == RETURN_ERR)
1508 {
1509 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1510 return RETURN_ERR;
1511 }
1512
1513
1514 ch2=strchr(str,'\n');
1515 //replace \n with \0
1516 *ch2='\0';
1517 ch2=strchr(str,'=');
1518 if(ch2==NULL)
1519 {
1520 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1521 return RETURN_ERR;
1522 }
1523 else
1524 wifi_dbg_printf("%s",ch2+1);
1525 ch2++;
1526
1527
1528 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1529 memset(buf,'\0',sizeof(buf));
1530 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1531 {
1532 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1533 return RETURN_ERR;
1534 }
1535
1536
1537 if(strstr(buf,"2.4")!=NULL)
1538 {
1539 strcpy(output_string,"2.4GHz");
1540 }
1541 if(strstr(buf,"5.")!=NULL)
1542 {
1543 strcpy(output_string,"5GHz");
1544 }
1545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1546 return RETURN_OK;
1547#endif
1548}
1549
1550//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1551//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.
1552INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1553{
developer963da0c2022-09-13 15:58:27 +08001554 char cmd[128]={0};
1555 char buf[128]={0};
1556 char temp_output[128] = {0};
1557 wifi_band band;
1558
1559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001560 if (NULL == output_string)
1561 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001562
1563 band = wifi_index_to_band(radioIndex);
1564 if (band == band_2_4) {
1565 strcat(temp_output, "b,g,");
1566 } else if (band == band_5) {
1567 strcat(temp_output, "a,");
1568 }
1569
1570 // ht capabilities
1571 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1572 _syscmd(cmd, buf, sizeof(buf));
1573 if (strncmp(buf, "0x00", 4) != 0) {
1574 strcat(temp_output, "n,");
1575 }
developer06a01d92022-09-07 16:32:39 +08001576
developer963da0c2022-09-13 15:58:27 +08001577 // vht capabilities
1578 if (band == band_5) {
1579 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1580 _syscmd(cmd, buf, sizeof(buf));
1581 if (strncmp(buf, "0x00000000", 10) != 0) {
1582 strcat(temp_output, "ac,");
1583 }
1584 }
1585
1586 // he capabilities
1587 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", radioIndex);
1588 _syscmd(cmd, buf, sizeof(buf));
1589 if (strncmp (buf, "0x0000", 6) != 0) {
1590 strcat(temp_output, "ax,");
1591 }
1592
1593 // Remove the last comma
1594 if (strlen(temp_output) != 0)
1595 temp_output[strlen(temp_output)-1] = '\0';
1596 strncpy(output_string, temp_output, strlen(temp_output));
1597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001598 return RETURN_OK;
1599}
1600
1601//Get the radio operating mode, and pure mode flag. eg: "ac"
1602//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.
1603INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1604{
1605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1606 if (NULL == output_string)
1607 return RETURN_ERR;
1608
1609 if (radioIndex == 0) {
1610 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1611 *gOnly = FALSE;
1612 *nOnly = TRUE;
1613 *acOnly = FALSE;
1614 } else {
1615 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1616 *gOnly = FALSE;
1617 *nOnly = FALSE;
1618 *acOnly = FALSE;
1619 }
1620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1621
1622 return RETURN_OK;
1623#if 0
1624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1625 char buf[64] = {0};
1626 char config_file[MAX_BUF_SIZE] = {0};
1627
1628 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1629 return RETURN_ERR;
1630
1631 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1632 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1633
1634 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1635 if (strlen(buf) == 0)
1636 {
1637 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1638 return RETURN_ERR;
1639 }
1640 if(strcmp(buf,"g")==0)
1641 {
1642 wifi_dbg_printf("\nG\n");
1643 *gOnly=TRUE;
1644 *nOnly=FALSE;
1645 *acOnly=FALSE;
1646 }
1647 else if(strcmp(buf,"n")==0)
1648 {
1649 wifi_dbg_printf("\nN\n");
1650 *gOnly=FALSE;
1651 *nOnly=TRUE;
1652 *acOnly=FALSE;
1653 }
1654 else if(strcmp(buf,"ac")==0)
1655 {
1656 wifi_dbg_printf("\nac\n");
1657 *gOnly=FALSE;
1658 *nOnly=FALSE;
1659 *acOnly=TRUE;
1660 }
1661 /* hostapd-5G.conf has "a" as hw_mode */
1662 else if(strcmp(buf,"a")==0)
1663 {
1664 wifi_dbg_printf("\na\n");
1665 *gOnly=FALSE;
1666 *nOnly=FALSE;
1667 *acOnly=FALSE;
1668 }
1669 else
1670 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1671
1672 //for a,n mode
1673 if(radioIndex == 1)
1674 {
1675 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1676 if(strcmp(buf,"1")==0)
1677 {
1678 strncpy(output_string, "n", 1);
1679 *nOnly=FALSE;
1680 }
1681 }
1682
1683 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1685 return RETURN_OK;
1686#endif
1687}
1688
developerdb744382022-09-13 15:34:54 +08001689INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1690{
1691 char cmd[128] = {0};
1692 char buf[64] = {0};
1693 char config_file[64] = {0};
1694 wifi_band band;
1695
1696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1697 if(NULL == output_string || NULL == pureMode)
1698 return RETURN_ERR;
1699
1700 // grep all of the ieee80211 protocol config set to 1
1701 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1702 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1703 _syscmd(cmd, buf, sizeof(buf));
1704
1705 band = wifi_index_to_band(radioIndex);
1706 // puremode is a bit map
1707 *pureMode = 0;
1708 if (band == band_2_4) {
1709 strcat(output_string, "b,g");
1710 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1711 if (strstr(buf, "n") != NULL) {
1712 strcat(output_string, ",n");
1713 *pureMode |= WIFI_MODE_N;
1714 }
1715 if (strstr(buf, "ax") != NULL) {
1716 strcat(output_string, ",ax");
1717 *pureMode |= WIFI_MODE_AX;
1718 }
1719 } else if (band == band_5) {
1720 strcat(output_string, "a");
1721 *pureMode |= WIFI_MODE_A;
1722 if (strstr(buf, "n") != NULL) {
1723 strcat(output_string, ",n");
1724 *pureMode |= WIFI_MODE_N;
1725 }
1726 if (strstr(buf, "ac") != NULL) {
1727 strcat(output_string, ",ac");
1728 *pureMode |= WIFI_MODE_AC;
1729 }
1730 if (strstr(buf, "ax") != NULL) {
1731 strcat(output_string, ",ax");
1732 *pureMode |= WIFI_MODE_AX;
1733 }
1734 } else if (band == band_6) {
1735 if (strstr(buf, "ax") != NULL) {
1736 strcat(output_string, "ax");
1737 *pureMode |= WIFI_MODE_AX;
1738 }
1739 }
1740
1741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1742 return RETURN_OK;
1743}
1744
1745// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001746INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1747{
1748 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1749 if (strcmp (channelMode,"11A") == 0)
1750 {
1751 writeBandWidth(radioIndex,"20MHz");
1752 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1753 printf("\nChannel Mode is 802.11a (5GHz)\n");
1754 }
1755 else if (strcmp (channelMode,"11NAHT20") == 0)
1756 {
1757 writeBandWidth(radioIndex,"20MHz");
1758 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1759 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1760 }
1761 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1762 {
1763 writeBandWidth(radioIndex,"40MHz");
1764 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1765 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1766 }
1767 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1768 {
1769 writeBandWidth(radioIndex,"40MHz");
1770 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1771 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1772 }
1773 else if (strcmp (channelMode,"11ACVHT20") == 0)
1774 {
1775 writeBandWidth(radioIndex,"20MHz");
1776 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1777 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1778 }
1779 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1780 {
1781 writeBandWidth(radioIndex,"40MHz");
1782 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1783 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1784 }
1785 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1786 {
1787 writeBandWidth(radioIndex,"40MHz");
1788 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1789 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1790 }
1791 else if (strcmp (channelMode,"11ACVHT80") == 0)
1792 {
1793 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1794 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1795 }
1796 else if (strcmp (channelMode,"11ACVHT160") == 0)
1797 {
1798 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1799 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1800 }
1801 else if (strcmp (channelMode,"11B") == 0)
1802 {
1803 writeBandWidth(radioIndex,"20MHz");
1804 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1805 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1806 }
1807 else if (strcmp (channelMode,"11G") == 0)
1808 {
1809 writeBandWidth(radioIndex,"20MHz");
1810 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1811 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1812 }
1813 else if (strcmp (channelMode,"11NGHT20") == 0)
1814 {
1815 writeBandWidth(radioIndex,"20MHz");
1816 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1817 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1818 }
1819 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1820 {
1821 writeBandWidth(radioIndex,"40MHz");
1822 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1823 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1824 }
1825 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1826 {
1827 writeBandWidth(radioIndex,"40MHz");
1828 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1829 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1830 }
1831 else
1832 {
1833 return RETURN_ERR;
1834 }
1835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1836
1837 return RETURN_OK;
1838}
1839
developerdb744382022-09-13 15:34:54 +08001840// Set the radio operating mode, and pure mode flag.
1841INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1842{
1843 int num_hostapd_support_mode = 3; // n, ac, ax
1844 struct params list[num_hostapd_support_mode];
1845 char config_file[64] = {0};
1846 char bandwidth[16] = {0};
1847 int mode_check_bit = 1 << 3; // n mode
1848 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1849
1850 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1851 // Set radio mode
1852 list[0].name = "ieee80211n";
1853 list[1].name = "ieee80211ac";
1854 list[2].name = "ieee80211ax";
1855 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1856
1857 // check the bit map from n to ax, and set hostapd config
1858 if (mode & WIFI_MODE_N)
1859 list[0].value = "1";
1860 else
1861 list[0].value = "0";
1862 if (mode & WIFI_MODE_AC)
1863 list[1].value = "1";
1864 else
1865 list[1].value = "0";
1866 if (mode & WIFI_MODE_AX)
1867 list[2].value = "1";
1868 else
1869 list[2].value = "0";
1870 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1871
1872 if (channelMode == NULL || strlen(channelMode) == 0)
1873 return RETURN_OK;
1874 // Set bandwidth
1875 if (strstr(channelMode, "40") != NULL)
1876 strcpy(bandwidth, "40MHz");
1877 else if (strstr(channelMode, "80") != NULL)
1878 strcpy(bandwidth, "80MHz");
1879 else if (strstr(channelMode, "160") != NULL)
1880 strcpy(bandwidth, "160MHz");
1881 else // 11A, 11B, 11G....
1882 strcpy(bandwidth, "20MHz");
1883
1884 writeBandWidth(radioIndex, bandwidth);
1885 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1886
1887 wifi_reloadAp(radioIndex);
1888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1889
1890 return RETURN_OK;
1891}
1892
developer06a01d92022-09-07 16:32:39 +08001893//Get the list of supported channel. eg: "1-11"
1894//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.
1895INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
1896{
developer6318ed52022-09-13 15:17:58 +08001897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001898 if (NULL == output_string)
1899 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08001900 char cmd[256] = {0};
1901 char buf[128] = {0};
1902 BOOL dfs_enable = false;
1903 // Parse possible channel number and separate them with commas.
1904 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
1905 if (dfs_enable)
1906 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
1907 else
1908 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);
1909
1910 _syscmd(cmd,buf,sizeof(buf));
1911 strncpy(output_string, buf, sizeof(buf));
1912
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1914 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08001915#if 0
1916 char IFName[50] ={0};
1917 char buf[MAX_BUF_SIZE] = {0};
1918 char cmd[MAX_CMD_SIZE] = {0};
1919 int count = 0;
1920 if (NULL == output_string)
1921 return RETURN_ERR;
1922
1923 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1924 if(radioIndex == 0)
1925 {
1926 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
1927 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'");
1928 }
1929 else if(radioIndex == 1)
1930 {
1931 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
1932 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'");
1933 }
1934 _syscmd(cmd, buf, sizeof(buf));
1935 if(strlen(buf) > 0)
1936 strcpy(output_string,buf);
1937 else
1938 strcpy(output_string,"0");
1939#endif
1940 return RETURN_OK;
1941}
1942
1943//Get the list for used channel. eg: "1,6,9,11"
1944//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.
1945INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
1946{
1947 if (NULL == output_string)
1948 return RETURN_ERR;
1949 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
1950#if 0
1951 char IFName[50] ={0};
1952 char buf[MAX_BUF_SIZE] = {0};
1953 char cmd[MAX_CMD_SIZE] = {0};
1954 if (NULL == output_string)
1955 return RETURN_ERR;
1956
1957 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
1958 if(radioIndex == 0)
1959 {
1960 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
1961 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'");
1962 }
1963 else if(radioIndex == 1)
1964 {
1965 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
1966 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'");
1967 }
1968 _syscmd(cmd,buf, sizeof(buf));
1969 if(strlen(buf) > 0)
1970 strcpy(output_string,buf);
1971 else
1972 strcpy(output_string,"0");
1973#endif
1974 return RETURN_OK;
1975}
1976
1977//Get the running channel number
1978INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
1979{
developerda1ed692022-09-13 13:59:20 +08001980#ifdef MTK_IMPL
1981 if(!wifi_getApChannel(radioIndex, output_ulong))
1982 return RETURN_OK;
1983 else
1984 return RETURN_ERR;
1985#else
developer06a01d92022-09-07 16:32:39 +08001986 char cmd[1024] = {0}, buf[5] = {0};
1987
1988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1989 if (NULL == output_ulong)
1990 return RETURN_ERR;
1991
1992 snprintf(cmd, sizeof(cmd),
1993 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
1994 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
1995 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
1996 _syscmd(cmd, buf, sizeof(buf));
1997
1998 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
1999 if (*output_ulong <= 0) {
2000 *output_ulong = 0;
2001 return RETURN_ERR;
2002 }
2003
2004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2005 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002006#endif
developer06a01d92022-09-07 16:32:39 +08002007}
2008
2009
2010INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2011{
2012 char cmd[1024] = {0}, buf[5] = {0};
2013 char interface_name[50] = {0};
2014
2015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2016 if (NULL == output_ulong)
2017 return RETURN_ERR;
2018
2019 wifi_getApName(apIndex,interface_name);
2020 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2021 _syscmd(cmd,buf,sizeof(buf));
2022 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2023 if (*output_ulong == 0) {
2024 return RETURN_ERR;
2025 }
2026
2027 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2028 return RETURN_OK;
2029}
2030
2031//Storing the previous channel value
2032INT wifi_storeprevchanval(INT radioIndex)
2033{
2034 char buf[256] = {0};
2035 char output[4]={'\0'};
2036 char config_file[MAX_BUF_SIZE] = {0};
2037 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2038 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2039 if(radioIndex == 0)
2040 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2041 else if(radioIndex == 1)
2042 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2043 system(buf);
2044 Radio_flag = FALSE;
2045 return RETURN_OK;
2046}
2047
2048//Set the running channel number
2049INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2050{
2051 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2052 struct params params={'\0'};
2053 char str_channel[4]={'\0'};
2054 struct params list;
2055 char config_file[MAX_BUF_SIZE] = {0};
2056
2057 list.name = "channel";
2058
2059 if(Radio_flag == TRUE)
2060 wifi_storeprevchanval(radioIndex); //for autochannel
2061
2062 if(radioIndex == 0)
2063 {
2064 switch(channel)
2065 {
2066 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2067 sprintf(str_channel,"%ld", channel);
2068 list.value = str_channel;
2069 break;
2070 default:
2071 return RETURN_ERR;
2072 }
2073 }
2074 else if(radioIndex == 1)
2075 {
2076 switch(channel)
2077 {
2078 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:
2079 sprintf(str_channel,"%ld", channel);
2080 list.value = str_channel;
2081 break;
2082 default:
2083 return RETURN_ERR;
2084 }
2085 }
2086
2087 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2088 {
2089 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2090 wifi_hostapdWrite(config_file,&list,1);
2091 }
2092
2093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2094 return RETURN_OK;
2095 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2096 }
2097
2098INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2099{
2100 struct params list;
2101 char str_idx[16];
2102 char config_file[MAX_BUF_SIZE];
2103
2104 list.name = "vht_oper_centr_freq_seg0_idx";
2105 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2106 list.value = str_idx;
2107
2108 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2109 {
2110 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2111 wifi_hostapdWrite(config_file, &list, 1);
2112 }
2113
2114 return RETURN_OK;
2115}
2116
2117//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2118//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2119INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2120{
2121 //Set to wifi config only. Wait for wifi reset to apply.
2122 char buf[256] = {0};
2123 char str_channel[256] = {0};
2124 int count = 0;
2125 ULONG Value = 0;
2126 FILE *fp = NULL;
2127 if(enable == TRUE)
2128 {
2129 if(radioIndex == 0)
2130 {
2131 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2132 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2133 }
2134 else if(radioIndex == 1)
2135 {
2136 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2137 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2138 }
2139 if(fp == NULL) //first time boot-up
2140 {
2141 if(radioIndex == 0)
2142 Value = 6;
2143 else if(radioIndex == 1)
2144 Value = 36;
2145 }
2146 else
2147 {
2148 if(fgets(buf,sizeof(buf),fp) != NULL)
2149 {
2150 for(count = 0;buf[count]!='\n';count++)
2151 str_channel[count] = buf[count];
2152 str_channel[count] = '\0';
2153 Value = atol(str_channel);
2154 printf("%sValue is %ld \n",__FUNCTION__,Value);
2155 pclose(fp);
2156 }
2157 }
2158 Radio_flag = FALSE;//for storing previous channel value
2159 wifi_setRadioChannel(radioIndex,Value);
2160 return RETURN_OK;
2161 }
2162 return RETURN_ERR;
2163}
2164
2165INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2166{
2167 if (NULL == output_bool)
2168 return RETURN_ERR;
2169 *output_bool=FALSE;
2170 return RETURN_OK;
2171}
2172
2173INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2174{
2175 if (NULL == output_bool)
2176 return RETURN_ERR;
2177 *output_bool=FALSE;
2178 return RETURN_OK;
2179}
2180
2181INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2182{
2183 //Set to wifi config only. Wait for wifi reset to apply.
2184 return RETURN_OK;
2185}
2186
2187INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2188{
2189 return RETURN_OK;
2190}
2191
2192INT wifi_factoryResetAP(int apIndex)
2193{
2194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2195 //factory reset is not done for now on Turris
2196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2197 return RETURN_OK;
2198}
2199
2200//To set Band Steering AP group
2201//To-do
2202INT wifi_setBandSteeringApGroup(char *ApGroup)
2203{
2204 return RETURN_OK;
2205}
2206
2207INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2208{
developer5f222492022-09-13 15:21:52 +08002209 struct params params={0};
2210 char config_file[MAX_BUF_SIZE] = {'\0'};
2211 char buf[MAX_BUF_SIZE] = {'\0'};
2212
2213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2214 if (dtimInterval < 1 || dtimInterval > 255) {
2215 return RETURN_ERR;
2216 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2217 }
2218
2219 params.name = "dtim_period";
2220 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2221 params.value = buf;
2222
2223 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2224 wifi_hostapdWrite(config_file, &params, 1);
2225 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2226
2227 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2228 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002229}
2230
2231//Check if the driver support the Dfs
2232INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2233{
2234 if (NULL == output_bool)
2235 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002236 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002237 return RETURN_OK;
2238}
2239
2240//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.
2241//The value of this parameter is a comma seperated list of channel number
2242INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2243{
2244 if (NULL == output_pool)
2245 return RETURN_ERR;
2246 if (radioIndex==1)
2247 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2248 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2249
2250 return RETURN_OK;
2251}
2252
2253INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2254{
2255 //Set to wifi config. And apply instantly.
2256 return RETURN_OK;
2257}
2258
2259INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2260{
2261 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2262 return RETURN_ERR;
2263 *output_interval_seconds=1800;
2264 *output_dwell_milliseconds=40;
2265
2266 return RETURN_OK;
2267}
2268
2269INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2270{
2271 //Set to wifi config. And apply instantly.
2272 return RETURN_OK;
2273}
2274
2275//Get the Dfs enable status
2276INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2277{
developer9964b5b2022-09-13 15:59:34 +08002278 char buf[16] = {0};
2279 FILE *f = NULL;
2280 wifi_band band;
2281
2282 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2283
2284 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002285 if (NULL == output_bool)
2286 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002287
2288 band = wifi_index_to_band(radioIndex);
2289 if (band != band_5)
2290 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002291
developer9964b5b2022-09-13 15:59:34 +08002292 f = fopen(DFS_ENABLE_FILE, "r");
2293 if (f != NULL) {
2294 fgets(buf, 2, f);
2295 if (strncmp(buf, "0", 0) == 0)
2296 *output_bool = FALSE;
2297 fclose(f);
2298 }
2299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002300 return RETURN_OK;
2301}
2302
2303//Set the Dfs enable status
2304INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2305{
developer9964b5b2022-09-13 15:59:34 +08002306 char buf[128] = {0};
2307 char config_file[128] = {0};
2308 FILE *f = NULL;
2309 struct params params={0};
2310 wifi_band band;
2311
2312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2313
2314 band = wifi_index_to_band(radioIndex);
2315 if (band != band_5)
2316 return RETURN_OK;
2317
2318 f = fopen(DFS_ENABLE_FILE, "w");
2319 if (f == NULL)
2320 return RETURN_ERR;
2321 fprintf(f, "%d", enable);
2322 fclose(f);
2323
2324 params.name = "acs_exclude_dfs";
2325 sprintf(buf, "%d", enable?"1":"0");
2326 params.value = buf;
2327 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2328 wifi_hostapdWrite(config_file, &params, 1);
2329 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2330
2331 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2332
2333 wifi_reloadAp(radioIndex);
2334
2335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002336}
2337
2338//Check if the driver support the AutoChannelRefreshPeriod
2339INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2340{
2341 if (NULL == output_bool)
2342 return RETURN_ERR;
2343 *output_bool=FALSE; //not support
2344
2345 return RETURN_OK;
2346}
2347
2348//Get the ACS refresh period in seconds
2349INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2350{
2351 if (NULL == output_ulong)
2352 return RETURN_ERR;
2353 *output_ulong=300;
2354
2355 return RETURN_OK;
2356}
2357
2358//Set the ACS refresh period in seconds
2359INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2360{
2361 return RETURN_ERR;
2362}
2363
2364//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2365//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.
2366INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2367{
developer70490032022-09-13 15:45:20 +08002368 char cmd[128] = {0}, buf[64] = {0};
2369 char interface_name[64] = {0};
2370 int ret = 0, len=0;
2371 BOOL radio_enable = FALSE;
2372
2373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2374
developer06a01d92022-09-07 16:32:39 +08002375 if (NULL == output_string)
2376 return RETURN_ERR;
2377
developer70490032022-09-13 15:45:20 +08002378 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2379 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002380
developer70490032022-09-13 15:45:20 +08002381 if (radio_enable != TRUE)
2382 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002383
developer70490032022-09-13 15:45:20 +08002384 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002385 ret = _syscmd(cmd, buf, sizeof(buf));
2386 len = strlen(buf);
2387 if((ret != 0) || (len == 0))
2388 {
2389 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2390 return RETURN_ERR;
2391 }
2392
2393 buf[len-1] = '\0';
2394 snprintf(output_string, 64, "%sMHz", buf);
2395 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2396
2397#if 0
2398 //TODO: revisit below implementation
2399 char output_buf[8]={0};
2400 char bw_value[10];
2401 char config_file[MAX_BUF_SIZE] = {0};
2402
2403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2404 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2405 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2406 readBandWidth(radioIndex,bw_value);
2407
2408 if(strstr (output_buf,"0") != NULL )
2409 {
2410 strcpy(output_string,bw_value);
2411 }
2412 else if (strstr (output_buf,"1") != NULL)
2413 {
2414 strcpy(output_string,"80MHz");
2415 }
2416 else if (strstr (output_buf,"2") != NULL)
2417 {
2418 strcpy(output_string,"160MHz");
2419 }
2420 else if (strstr (output_buf,"3") != NULL)
2421 {
2422 strcpy(output_string,"80+80");
2423 }
2424 else
2425 {
2426 strcpy(output_string,"Auto");
2427 }
2428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2429#endif
2430
2431 return RETURN_OK;
2432}
2433
2434//Set the Operating Channel Bandwidth.
2435INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181 //AP only
2436{
2437 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2438 char config_file[MAX_BUF_SIZE];
2439 struct params params[4];
2440 struct params *pptr = params;
2441
2442 if(NULL == output_string)
2443 return RETURN_ERR;
2444
2445 pptr->name = "vht_oper_chwidth";
2446 if(strcmp(output_string,"20MHz") == 0) // This piece of code only support for wifi hal api's validation
2447 pptr->value="0";
2448 else if(strcmp(output_string,"40MHz") == 0)
2449 pptr->value="0";
2450 else if(strcmp(output_string,"80MHz") == 0)
2451 pptr->value="1";
2452 else if(strcmp(output_string,"160MHz") == 0)
2453 pptr->value="2";
2454 else if(strcmp(output_string,"80+80") == 0)
2455 pptr->value="3";
2456 else
2457 {
2458 printf("Invalid Bandwidth \n");
2459 return RETURN_ERR;
2460 }
2461
2462 pptr++; // added vht_oper_chwidth
2463
2464 if(radioIndex == 1)
2465 {
2466 pptr->name= "ieee80211n";
2467 if(strcmp(output_string,"20MHz") == 0)
2468 pptr->value="0";
2469 else if(strcmp(output_string,"40MHz") == 0)
2470 pptr->value="1";
2471 else if(strcmp(output_string,"80MHz") == 0)
2472 pptr->value="1";
2473 else
2474 pptr->value="0";
2475
2476 pptr++; // added ieee80211n
2477
2478 pptr->name="ieee80211ac";
2479 if(strcmp(output_string,"80MHz") == 0)
2480 pptr->value="1";
2481 else
2482 pptr->value="0";
2483 pptr++;
2484 }
2485
2486 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2487 {
2488 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2489 wifi_hostapdWrite(config_file, params, (pptr - params));
2490 }
2491
2492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2493 return RETURN_OK;
2494}
2495
2496//Getting current radio extension channel
2497INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2498{
2499 CHAR buf[150] = {0};
2500 CHAR cmd[150] = {0};
2501 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2502 _syscmd(cmd, buf, sizeof(buf));
2503 if(NULL != strstr(buf,"HT40+"))
2504 strcpy(Value,"AboveControlChannel");
2505 else if(NULL != strstr(buf,"HT40-"))
2506 strcpy(Value,"BelowControlChannel");
2507 return RETURN_OK;
2508}
2509
2510//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2511//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.
2512INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2513{
2514 if (NULL == output_string)
2515 return RETURN_ERR;
2516
2517 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2518#if 0
2519 CHAR Value[100] = {0};
2520 if (NULL == output_string)
2521 return RETURN_ERR;
2522 if(radioIndex == 0)
2523 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2524 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2525 {
2526 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2527 if(strcmp(Value,"40MHz") == 0)
2528 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2529 else
2530 strcpy(Value,"Auto");
2531 }
2532 strcpy(output_string,Value);
2533#endif
2534
2535 return RETURN_OK;
2536}
2537
2538//Set the extension channel.
2539INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2540{
2541 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2542 struct params params={'\0'};
2543 char config_file[MAX_BUF_SIZE] = {0};
2544 char ext_channel[127]={'\0'};
2545
2546 params.name = "ht_capab";
2547
2548 if(radioIndex == 0)
2549 {
2550 if(NULL!= strstr(string,"Above"))
2551 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2552 else if(NULL!= strstr(string,"Below"))
2553 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2554 else
2555 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2556 }
2557 else if(radioIndex == 1)
2558 {
2559 if(NULL!= strstr(string,"Above"))
2560 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40+]");
2561 else if(NULL!= strstr(string,"Below"))
2562 strcpy(ext_channel, HOSTAPD_HT_CAPAB_40 "[HT40-]");
2563 else
2564 strcpy(ext_channel, HOSTAPD_HT_CAPAB_20);
2565 }
2566
2567 params.value = ext_channel;
2568 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2569 {
2570 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2571 wifi_hostapdWrite(config_file, &params, 1);
2572 }
2573
2574 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576 return RETURN_OK;
2577}
2578
2579//Get the guard interval value. eg "400nsec" or "800nsec"
2580//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.
2581INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2582{
developer454b9462022-09-13 15:29:16 +08002583 wifi_guard_interval_t GI;
2584
2585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2586
2587 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002588 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002589
2590 if (GI == wifi_guard_interval_400)
2591 strcpy(output_string, "400nsec");
2592 else if (GI == wifi_guard_interval_800)
2593 strcpy(output_string, "800nsec");
2594 else if (GI == wifi_guard_interval_1600)
2595 strcpy(output_string, "1600nsec");
2596 else if (GI == wifi_guard_interval_3200)
2597 strcpy(output_string, "3200nsec");
2598 else
2599 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002600
developer454b9462022-09-13 15:29:16 +08002601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002602 return RETURN_OK;
2603}
2604
2605//Set the guard interval value.
2606INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2607{
developer454b9462022-09-13 15:29:16 +08002608 wifi_guard_interval_t GI;
2609 int ret = 0;
2610
2611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2612
2613 if (strcmp(string, "400nsec") == 0)
2614 GI = wifi_guard_interval_400;
2615 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2616 GI = wifi_guard_interval_800;
2617 else if (strcmp(string , "1600nsec") == 0)
2618 GI = wifi_guard_interval_1600;
2619 else if (strcmp(string , "3200nsec") == 0)
2620 GI = wifi_guard_interval_3200;
2621
2622 ret = wifi_setGuardInterval(radioIndex, GI);
2623
2624 if (ret == RETURN_ERR) {
2625 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2626 return RETURN_ERR;
2627 }
2628
2629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2630 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002631}
2632
2633//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2634INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2635{
2636 if (NULL == output_int)
2637 return RETURN_ERR;
2638 *output_int=(radioIndex==0)?1:3;
2639
2640 return RETURN_OK;
2641}
2642
2643//Set the Modulation Coding Scheme index
2644INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2645{
2646 return RETURN_ERR;
2647}
2648
2649//Get supported Transmit Power list, eg : "0,25,50,75,100"
2650//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.
2651INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2652{
2653 if (NULL == output_list)
2654 return RETURN_ERR;
2655 snprintf(output_list, 64,"0,25,50,75,100");
2656 return RETURN_OK;
2657}
2658
developera5005b62022-09-13 15:43:35 +08002659//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002660//The transmite power level is in units of full power for this radio.
2661INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2662{
2663 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002664 char buf[16]={0};
2665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002666
developera5005b62022-09-13 15:43:35 +08002667 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002668 return RETURN_ERR;
2669
developera5005b62022-09-13 15:43:35 +08002670 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002671 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002672
developera5005b62022-09-13 15:43:35 +08002673 *output_ulong = strtol(buf, NULL, 10);
2674
2675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002676 return RETURN_OK;
2677}
2678
2679//Set Transmit Power
2680//The transmite power level is in units of full power for this radio.
2681INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2682{
developera5005b62022-09-13 15:43:35 +08002683 char *support;
developer06a01d92022-09-07 16:32:39 +08002684 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002685 char buf[128]={0};
2686 char txpower_str[64] = {0};
2687 int txpower = 0;
2688 int maximum_tx = 0;
2689
2690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002691
developera5005b62022-09-13 15:43:35 +08002692 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002693 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002694 maximum_tx = strtol(buf, NULL, 10);
2695
2696 // Get the Tx power supported list and check that is the input in the list
2697 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2698 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2699 support = strtok(buf, ",");
2700 while(true)
2701 {
2702 if(support == NULL) { // input not in the list
2703 wifi_dbg_printf("Input value is invalid.\n");
2704 return RETURN_ERR;
2705 }
2706 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2707 break;
2708 }
2709 support = strtok(NULL, ",");
2710 }
2711 txpower = TransmitPower*maximum_tx/100;
2712 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2713 _syscmd(cmd, buf, sizeof(buf));
2714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002715
2716 return RETURN_OK;
2717}
2718
2719//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2720INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2721{
2722 if (NULL == Supported)
2723 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002724 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002725
2726 return RETURN_OK;
2727}
2728
2729//Get 80211h feature enable
2730INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2731{
developer3885fec2022-09-13 15:13:47 +08002732 char buf[64]={'\0'};
2733 char config_file[64] = {'\0'};
2734
2735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2736 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002737 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002738
2739 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2740 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002741
developer3885fec2022-09-13 15:13:47 +08002742 if (strncmp(buf, "1", 1) == 0)
2743 *enable = TRUE;
2744 else
2745 *enable = FALSE;
2746
2747 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002748 return RETURN_OK;
2749}
2750
2751//Set 80211h feature enable
2752INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2753{
developer3885fec2022-09-13 15:13:47 +08002754 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2755 struct params params={'\0'};
2756 char config_file[MAX_BUF_SIZE] = {0};
2757
2758 params.name = "ieee80211h";
2759
2760 if (enable) {
2761 params.value = "1";
2762 } else {
2763 params.value = "0";
2764 }
2765
2766 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2767 wifi_hostapdWrite(config_file, &params, 1);
2768
2769 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2770 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2771 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002772}
2773
2774//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.
2775INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2776{
2777 if (NULL == output)
2778 return RETURN_ERR;
2779 *output=100;
2780
2781 return RETURN_OK;
2782}
2783
2784//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.
2785INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2786{
2787 if (NULL == output)
2788 return RETURN_ERR;
2789 *output = -99;
2790
2791 return RETURN_OK;
2792}
2793
2794INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2795{
2796 return RETURN_ERR;
2797}
2798
2799
2800//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2801INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2802{
developer5f222492022-09-13 15:21:52 +08002803 char cmd[MAX_BUF_SIZE]={'\0'};
2804 char buf[MAX_CMD_SIZE]={'\0'};
2805
2806 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2807 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002808 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002809
2810 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2811 _syscmd(cmd, buf, sizeof(buf));
2812 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08002813
developer5f222492022-09-13 15:21:52 +08002814 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002815 return RETURN_OK;
2816}
2817
2818INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2819{
developer5f222492022-09-13 15:21:52 +08002820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2821 struct params params={'\0'};
2822 char buf[MAX_BUF_SIZE] = {'\0'};
2823 char config_file[MAX_BUF_SIZE] = {'\0'};
2824
2825 params.name = "beacon_int";
2826 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
2827 params.value = buf;
2828
2829 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2830 wifi_hostapdWrite(config_file, &params, 1);
2831
2832 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2833 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2834 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002835}
2836
2837//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.
2838INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2839{
developer06a01d92022-09-07 16:32:39 +08002840 //TODO: need to revisit below implementation
2841 char *temp;
developere9d0abd2022-09-13 15:40:57 +08002842 char temp_output[128] = {0};
2843 char temp_TransmitRates[64] = {0};
2844 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08002845
2846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2847 if (NULL == output)
2848 return RETURN_ERR;
2849 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08002850 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
2851
2852 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
2853 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
2854 } else {
2855 temp = strtok(temp_TransmitRates," ");
2856 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08002857 {
developere9d0abd2022-09-13 15:40:57 +08002858 // Convert 100 kbps to Mbps
2859 temp[strlen(temp)-1]=0;
2860 if((temp[0]=='5') && (temp[1]=='\0'))
2861 {
2862 temp="5.5";
2863 }
2864 strcat(temp_output,temp);
2865 temp = strtok(NULL," ");
2866 if(temp!=NULL)
2867 {
2868 strcat(temp_output,",");
2869 }
developer06a01d92022-09-07 16:32:39 +08002870 }
developere9d0abd2022-09-13 15:40:57 +08002871 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08002872 }
developer06a01d92022-09-07 16:32:39 +08002873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002874 return RETURN_OK;
2875}
2876
2877INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2878{
2879 char *temp;
2880 char temp1[128];
2881 char temp_output[128];
2882 char temp_TransmitRates[128];
2883 char set[128];
2884 char sub_set[128];
2885 int set_count=0,subset_count=0;
2886 int set_index=0,subset_index=0;
2887 char *token;
2888 int flag=0, i=0;
2889 struct params params={'\0'};
2890 char config_file[MAX_BUF_SIZE] = {0};
2891
2892 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2893 if(NULL == TransmitRates)
2894 return RETURN_ERR;
2895 strcpy(sub_set,TransmitRates);
2896
2897 //Allow only supported Data transmit rate to be set
2898 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
2899 token = strtok(sub_set,",");
2900 while( token != NULL ) /* split the basic rate to be set, by comma */
2901 {
2902 sub_set[subset_count]=atoi(token);
2903 subset_count++;
2904 token=strtok(NULL,",");
2905 }
2906 token=strtok(set,",");
2907 while(token!=NULL) /* split the supported rate by comma */
2908 {
2909 set[set_count]=atoi(token);
2910 set_count++;
2911 token=strtok(NULL,",");
2912 }
2913 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
2914 {
2915 for(set_index=0;set_index < set_count;set_index++)
2916 {
2917 flag=0;
2918 if(sub_set[subset_index]==set[set_index])
2919 break;
2920 else
2921 flag=1; /* No match found */
2922 }
2923 if(flag==1)
2924 return RETURN_ERR; //If value not found return Error
2925 }
2926 strcpy(temp_TransmitRates,TransmitRates);
2927
2928 for(i=0;i<strlen(temp_TransmitRates);i++)
2929 {
2930 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
2931 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
2932 {
2933 continue;
2934 }
2935 else
2936 {
2937 return RETURN_ERR;
2938 }
2939 }
2940 strcpy(temp_output,"");
2941 temp = strtok(temp_TransmitRates,",");
2942 while(temp!=NULL)
2943 {
2944 strcpy(temp1,temp);
2945 if(radioIndex==1)
2946 {
2947 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
2948 {
2949 return RETURN_ERR;
2950 }
2951 }
2952
2953 if(strcmp(temp,"5.5")==0)
2954 {
2955 strcpy(temp1,"55");
2956 }
2957 else
2958 {
2959 strcat(temp1,"0");
2960 }
2961 strcat(temp_output,temp1);
2962 temp = strtok(NULL,",");
2963 if(temp!=NULL)
2964 {
2965 strcat(temp_output," ");
2966 }
2967 }
2968 strcpy(TransmitRates,temp_output);
2969
2970 params.name= "basic_rates";
2971 params.value =TransmitRates;
2972
2973 wifi_dbg_printf("\n%s:",__func__);
2974 wifi_dbg_printf("\nparams.value=%s\n",params.value);
2975 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
2976 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2977 wifi_hostapdWrite(config_file,&params,1);
2978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2979 return RETURN_OK;
2980}
2981
2982//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
2983INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
2984{
2985 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2986 FILE *fp = NULL;
2987 char path[256] = {0}, output_string[256] = {0};
2988 int count = 0;
2989 char *interface = NULL;
2990
2991 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
2992 if (fp == NULL)
2993 {
2994 printf("Failed to run command in Function %s\n", __FUNCTION__);
2995 return RETURN_ERR;
2996 }
2997 if (fgets(path, sizeof(path) - 1, fp) != NULL)
2998 {
2999 interface = strchr(path, '=');
3000
3001 if (interface != NULL)
3002 {
3003 strcpy(output_string, interface + 1);
3004 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3005 interface_name[count] = output_string[count];
3006
3007 interface_name[count] = '\0';
3008 }
3009 }
3010 pclose(fp);
3011 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3012 return RETURN_OK;
3013}
3014
3015INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3016{
3017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3018 output_struct->radio_BytesSent = 0;
3019 output_struct->radio_BytesReceived = 0;
3020 output_struct->radio_PacketsSent = 0;
3021 output_struct->radio_PacketsReceived = 0;
3022 output_struct->radio_ErrorsSent = 0;
3023 output_struct->radio_ErrorsReceived = 0;
3024 output_struct->radio_DiscardPacketsSent = 0;
3025 output_struct->radio_DiscardPacketsReceived = 0;
3026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3027 return RETURN_OK;
3028}
3029
3030
3031INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3032{
3033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3034 CHAR buf[MAX_CMD_SIZE] = {0};
3035 CHAR Value[MAX_BUF_SIZE] = {0};
3036 FILE *fp = NULL;
3037
3038 if (ifname == NULL || strlen(ifname) <= 1)
3039 return RETURN_OK;
3040
3041 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3042 system(buf);
3043
3044 fp = fopen("/tmp/Radio_Stats.txt", "r");
3045 if(fp == NULL)
3046 {
3047 printf("/tmp/Radio_Stats.txt not exists \n");
3048 return RETURN_ERR;
3049 }
3050 fclose(fp);
3051
3052 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3053 File_Reading(buf, Value);
3054 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3055
3056 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3057 File_Reading(buf, Value);
3058 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3059
3060 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3061 File_Reading(buf, Value);
3062 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3063
3064 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3065 File_Reading(buf, Value);
3066 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3067
3068 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3069 File_Reading(buf, Value);
3070 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3071
3072 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3073 File_Reading(buf, Value);
3074 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3075
3076 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3077 File_Reading(buf, Value);
3078 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3079
3080 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3081 File_Reading(buf, Value);
3082 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3083
3084 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3085 return RETURN_OK;
3086}
3087
3088INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3089{
3090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3091 CHAR buf[MAX_CMD_SIZE] = {0};
3092 FILE *fp = NULL;
3093 INT count = 0;
3094
3095 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3096 {
3097 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3098 File_Reading(buf, status);
3099 }
3100 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3101 return RETURN_OK;
3102}
3103
3104//Get detail radio traffic static info
3105INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3106{
3107
3108#if 0
3109 //ifconfig radio_x
3110 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3111 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3112 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3113 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3114
3115 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3116 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3117 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.
3118 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.
3119
3120 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3121 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].
3122 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3123 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.
3124 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
3125 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
3126 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
3127 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
3128 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
3129
3130 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
3131 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
3132 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
3133 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.
3134
3135 return RETURN_OK;
3136#endif
3137
3138 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
3139 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
3140 char buf[MAX_BUF_SIZE] = {0};
3141 char cmd[MAX_CMD_SIZE] = {0};
3142 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
3143
3144 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3145 if (NULL == output_struct)
3146 return RETURN_ERR;
3147
3148 if (radioIndex == 0) //2.4GHz ?
3149 {
3150
3151 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
3152
3153 GetIfacestatus(private_interface_name, private_interface_status);
3154
3155 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
3156 File_Reading(cmd, buf);
3157
3158 if (buf[0] == '#')
3159 {
3160 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
3161 }
3162 else
3163 {
3164 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
3165 }
3166
3167 GetIfacestatus(public_interface_name, public_interface_status);
3168
3169 if (strcmp(private_interface_status, "1") == 0)
3170 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3171 else
3172 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3173
3174 if (strcmp(public_interface_status, "1") == 0)
3175 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3176 else
3177 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3178 }
3179 else if (radioIndex == 1) //5GHz ?
3180 {
3181 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
3182 GetIfacestatus(private_interface_name, private_interface_status);
3183
3184 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
3185 GetIfacestatus(public_interface_name, public_interface_status);
3186
3187 if (strcmp(private_interface_status, "1") == 0)
3188 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3189 else
3190 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3191
3192 if (strcmp(public_interface_status, "1") == 0)
3193 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3194 else
3195 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3196 }
3197
3198 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
3199 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
3200 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
3201 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
3202 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
3203 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
3204 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
3205 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
3206
3207 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3208 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].
3209 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3210 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.
3211 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
3212 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
3213 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
3214 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
3215 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
3216
3217 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
3218 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
3219 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
3220 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.
3221
3222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3223
3224 return RETURN_OK;
3225}
3226
3227//Set radio traffic static Measureing rules
3228INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3229{
3230 //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
3231 // Else, save the MeasuringRate and MeasuringInterval for future usage
3232
3233 return RETURN_OK;
3234}
3235
3236//To start or stop RadioTrafficStats
3237INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3238{
3239 //zqiu: If the RadioTrafficStats process running
3240 // if(enable)
3241 // return RETURN_OK.
3242 // else
3243 // Stop RadioTrafficStats process
3244 // Else
3245 // if(enable)
3246 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3247 // else
3248 // return RETURN_OK.
3249
3250 return RETURN_OK;
3251}
3252
3253//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
3254INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3255{
3256 //zqiu: Please ignor signalIndex.
3257 if (NULL == SignalLevel)
3258 return RETURN_ERR;
3259 *SignalLevel=(radioIndex==0)?-19:-19;
3260
3261 return RETURN_OK;
3262}
3263
3264//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3265INT wifi_applyRadioSettings(INT radioIndex)
3266{
3267 return RETURN_OK;
3268}
3269
3270//Get the radio index assocated with this SSID entry
3271INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3272{
3273 if (NULL == radioIndex)
3274 return RETURN_ERR;
3275 *radioIndex=ssidIndex%2;
3276
3277 return RETURN_OK;
3278}
3279
3280//Device.WiFi.SSID.{i}.Enable
3281//Get SSID enable configuration parameters (not the SSID enable status)
3282INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3283{
3284 if (NULL == output_bool)
3285 return RETURN_ERR;
3286
3287 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3288 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3289 return wifi_getApEnable(ssidIndex, output_bool);
3290}
3291
3292//Device.WiFi.SSID.{i}.Enable
3293//Set SSID enable configuration parameters
3294INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3295{
3296 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3297 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3298 return wifi_setApEnable(ssidIndex, enable);
3299}
3300
3301//Device.WiFi.SSID.{i}.Status
3302//Get the SSID enable status
3303INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3304{
3305 char cmd[MAX_CMD_SIZE]={0};
3306 char buf[MAX_BUF_SIZE]={0};
3307 BOOL output_bool;
3308
3309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3310 if (NULL == output_string)
3311 return RETURN_ERR;
3312 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3313 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3314
3315 wifi_getApEnable(ssidIndex,&output_bool);
3316 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3317
3318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3319 return RETURN_OK;
3320}
3321
3322// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3323INT wifi_getSSIDName(INT apIndex, CHAR *output)
3324{
3325 char config_file[MAX_BUF_SIZE] = {0};
3326
3327 if (NULL == output)
3328 return RETURN_ERR;
3329
3330 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3331 wifi_hostapdRead(config_file,"ssid",output,32);
3332
3333 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3334 return RETURN_OK;
3335}
3336
3337// Set a max 32 byte string and sets an internal variable to the SSID name
3338INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3339{
3340 char str[MAX_BUF_SIZE]={'\0'};
3341 char cmd[MAX_CMD_SIZE]={'\0'};
3342 struct params params;
3343 char config_file[MAX_BUF_SIZE] = {0};
3344
3345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3346 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3347 return RETURN_ERR;
3348
3349 params.name = "ssid";
3350 params.value = ssid_string;
3351 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3352 wifi_hostapdWrite(config_file, &params, 1);
3353 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3354 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3355
3356 return RETURN_OK;
3357}
3358
3359//Get the BSSID
3360INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3361{
3362 char cmd[MAX_CMD_SIZE]="";
3363
3364 if (NULL == output_string)
3365 return RETURN_ERR;
3366
3367 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3368 {
3369 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3370 _syscmd(cmd, output_string, 64);
3371 return RETURN_OK;
3372 }
3373 strncpy(output_string, "\0", 1);
3374
3375 return RETURN_ERR;
3376}
3377
3378//Get the MAC address associated with this Wifi SSID
3379INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3380{
3381 wifi_getBaseBSSID(ssidIndex,output_string);
3382 return RETURN_OK;
3383}
3384
3385//Get the basic SSID traffic static info
3386//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3387//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3388INT wifi_applySSIDSettings(INT ssidIndex)
3389{
3390 BOOL status = false;
3391 char cmd[MAX_CMD_SIZE] = {0};
3392 char buf[MAX_CMD_SIZE] = {0};
3393 int apIndex, ret;
3394 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3395
3396 wifi_getApEnable(ssidIndex,&status);
3397 // Do not apply when ssid index is disabled
3398 if (status == false)
3399 return RETURN_OK;
3400
3401 /* Doing full remove and add for ssid Index
3402 * Not all hostapd options are supported with reload
3403 * for example macaddr_acl
3404 */
3405 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3406 return RETURN_ERR;
3407
3408 ret = wifi_setApEnable(ssidIndex,true);
3409
3410 /* Workaround for hostapd issue with multiple bss definitions
3411 * when first created interface will be removed
3412 * then all vaps other vaps on same phy are removed
3413 * after calling setApEnable to false readd all enabled vaps */
3414 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3415 apIndex = 2*i+radioIndex;
3416 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3417 _syscmd(cmd, buf, sizeof(buf));
3418 if(*buf == '1')
3419 wifi_setApEnable(apIndex, true);
3420 }
3421
3422 return ret;
3423}
3424
developera3c68b92022-09-13 15:27:29 +08003425struct channels_noise {
3426 int channel;
3427 int noise;
3428};
3429
3430// Return noise array for each channel
3431int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3432{
3433 FILE *f = NULL;
3434 char cmd[128] = {0};
3435 char *line = NULL;
3436 size_t len = 0;
3437 ssize_t read = 0;
3438 int tmp = 0, arr_index = -1;
3439
3440 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3441
3442 if ((f = popen(cmd, "r")) == NULL) {
3443 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3444 return RETURN_ERR;
3445 }
3446 line = malloc(sizeof(char) * 256);
3447 while((read = getline(&line, &len, f)) != -1) {
3448 sscanf(line, "%d", &tmp);
3449 if (tmp > 0) { // channel frequency, the first line must be frequency
3450 arr_index++;
3451 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3452 } else { // noise
3453 channels_noise_arr[arr_index].noise = tmp;
3454 }
3455 }
3456 free(line);
3457 pclose(f);
3458 return RETURN_OK;
3459}
3460
developer06a01d92022-09-07 16:32:39 +08003461//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3462//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3463INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3464{
developera3c68b92022-09-13 15:27:29 +08003465 int index = -1;
3466 wifi_neighbor_ap2_t *scan_array = NULL;
3467 char cmd[256]={0};
3468 char buf[128]={0};
3469 char file_name[32] = {0};
3470 char filter_SSID[32] = {0};
3471 int freq=0;
3472 FILE *f = NULL;
3473 size_t len=0;
3474 ssize_t read = 0;
3475 char *line =NULL;
3476 // int noise_arr[channels_num] = {0};
3477 int channels_num = 0;
3478 int vht_channel_width = 0;
3479 bool get_nosie_ret = false;
3480 bool filter_enable = false;
3481 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003482
3483 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003484
3485 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3486 f = fopen(file_name, "r");
3487 if (f != NULL) {
3488 fgets(filter_SSID, sizeof(file_name), f);
3489 if (strlen(filter_SSID) != 0)
3490 filter_enable = true;
3491 fclose(f);
3492 }
3493
3494 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003495 _syscmd(cmd, buf, sizeof(buf));
developera3c68b92022-09-13 15:27:29 +08003496 channels_num = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003497
developera3c68b92022-09-13 15:27:29 +08003498 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3499 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003500
developera3c68b92022-09-13 15:27:29 +08003501 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3502 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
3503 fprintf(stderr, "cmd: %s\n", cmd);
3504 if ((f = popen(cmd, "r")) == NULL) {
3505 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3506 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003507 }
developera3c68b92022-09-13 15:27:29 +08003508 line = malloc(sizeof(char) * 256);
3509 while ((read = getline(&line, &len, f)) != -1) {
3510 if(strstr(line, "BSS") != NULL) { // new neighbor info
3511 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3512 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3513 // 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 +08003514
developera3c68b92022-09-13 15:27:29 +08003515 if (!filter_BSS) {
3516 index++;
3517 wifi_neighbor_ap2_t *tmp;
3518 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3519 if (tmp == NULL) { // no more memory to use
3520 index--;
3521 wifi_dbg_printf("%s: realloc failed\n", __func__);
3522 break;
3523 }
3524 scan_array = tmp;
3525 }
3526 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3527
3528 filter_BSS = false;
3529 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3530 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3531 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3532 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3533 } else if (strstr(line, "freq") != NULL) {
3534 sscanf(line," freq: %d", &freq);
3535 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3536
3537 if (freq >= 2412 && freq <= 2484) {
3538 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3539 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3540 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3541 }
3542 else if (freq >= 5160 && freq <= 5805) {
3543 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3544 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3545 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3546 }
3547
3548 scan_array[index].ap_Noise = 0;
3549 if (get_nosie_ret) {
3550 for (int i = 0; i < channels_num; i++) {
3551 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3552 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3553 break;
3554 }
3555 }
3556 }
3557 } else if (strstr(line, "beacon interval") != NULL) {
3558 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3559 } else if (strstr(line, "signal") != NULL) {
3560 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3561 } else if (strstr(line,"SSID") != NULL) {
3562 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3563 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3564 filter_BSS = true;
3565 }
3566 } else if (strstr(line, "Supported rates") != NULL) {
3567 char SRate[80] = {0}, *tmp = NULL;
3568 memset(buf, 0, sizeof(buf));
3569 strcpy(SRate, line);
3570 tmp = strtok(SRate, ":");
3571 tmp = strtok(NULL, ":");
3572 strcpy(buf, tmp);
3573 memset(SRate, 0, sizeof(SRate));
3574
3575 tmp = strtok(buf, " \n");
3576 while (tmp != NULL) {
3577 strcat(SRate, tmp);
3578 if (SRate[strlen(SRate) - 1] == '*') {
3579 SRate[strlen(SRate) - 1] = '\0';
3580 }
3581 strcat(SRate, ",");
3582
3583 tmp = strtok(NULL, " \n");
3584 }
3585 SRate[strlen(SRate) - 1] = '\0';
3586 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3587 } else if (strstr(line, "DTIM") != NULL) {
3588 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3589 } else if (strstr(line, "VHT capabilities") != NULL) {
3590 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3591 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3592 } else if (strstr(line, "HT capabilities") != NULL) {
3593 strcat(scan_array[index].ap_SupportedStandards, ",n");
3594 strcpy(scan_array[index].ap_OperatingStandards, "n");
3595 } else if (strstr(line, "VHT operation") != NULL) {
3596 read = getline(&line, &len, f);
3597 sscanf(line," * channel width: %d", &vht_channel_width);
3598 if(vht_channel_width == 1) {
3599 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3600 } else {
3601 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3602 }
3603 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3604 continue;
3605 } else if (strstr(line, "HT operation") != NULL) {
3606 read = getline(&line, &len, f);
3607 sscanf(line," * secondary channel offset: %s", &buf);
3608 if (!strcmp(buf, "above")) {
3609 //40Mhz +
3610 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3611 }
3612 else if (!strcmp(buf, "below")) {
3613 //40Mhz -
3614 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3615 } else {
3616 //20Mhz
3617 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3618 }
3619 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3620 continue;
3621 } else if (strstr(line, "HE capabilities") != NULL) {
3622 strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax"));
3623 strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax"));
3624 } else if (strstr(line, "HE PHY Capabilities") != NULL) {
3625 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3626 if (strstr(line, "HE40/2.4GHz") != NULL)
3627 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS"));
3628 else
3629 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20"));
3630 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
3631 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support
3632 read = getline(&line, &len, f);
3633 if (strstr(line, "HE160/5GHz") != NULL)
3634 strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160"));
3635 }
3636 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3637 continue;
3638 } else if (strstr(line, "WPA") != NULL) {
3639 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3640 } else if (strstr(line, "RSN") != NULL) {
3641 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3642 } else if (strstr(line, "Group cipher") != NULL) {
3643 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3644 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3645 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3646 }
3647 }
3648 }
3649
3650 if (!filter_BSS) {
3651 *output_array_size = index + 1;
3652 } else {
3653 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3654 *output_array_size = index;
3655 }
3656 *neighbor_ap_array = scan_array;
3657 free(line);
3658 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003659 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003660 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003661}
3662
3663//>> Deprecated: used for old RDKB code.
3664INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3665{
3666 INT status = RETURN_ERR;
3667
3668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3669 output_struct->wifi_PLCPErrorCount = 0;
3670 output_struct->wifi_FCSErrorCount = 0;
3671 output_struct->wifi_InvalidMACCount = 0;
3672 output_struct->wifi_PacketsOtherReceived = 0;
3673 output_struct->wifi_Noise = 0;
3674 status = RETURN_OK;
3675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3676 return status;
3677}
3678
3679INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3680{
3681 char cmd[128];
3682 char buf[1280];
3683 char *pos = NULL;
3684
3685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3686 if (NULL == output_struct)
3687 return RETURN_ERR;
3688
3689 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3690
3691 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3692 _syscmd(cmd, buf, sizeof(buf));
3693
3694 pos = buf;
3695 if ((pos = strstr(pos, "RX packets:")) == NULL)
3696 return RETURN_ERR;
3697 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3698
3699 if ((pos = strstr(pos, "TX packets:")) == NULL)
3700 return RETURN_ERR;
3701 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3702
3703 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3704 return RETURN_ERR;
3705 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3706
3707 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3708 return RETURN_ERR;
3709 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3710
3711 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3712 _syscmd(cmd, buf, sizeof(buf));
3713 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3714
3715#if 0
3716 //TODO: need to revisit below implementation
3717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3718 char interface_name[MAX_BUF_SIZE] = {0};
3719 char interface_status[MAX_BUF_SIZE] = {0};
3720 char Value[MAX_BUF_SIZE] = {0};
3721 char buf[MAX_CMD_SIZE] = {0};
3722 char cmd[MAX_CMD_SIZE] = {0};
3723 FILE *fp = NULL;
3724
3725 if (NULL == output_struct) {
3726 return RETURN_ERR;
3727 }
3728
3729 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3730
3731 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3732 {
3733 if(apIndex == 0) //private_wifi for 2.4G
3734 {
3735 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3736 }
3737 else if(apIndex == 1) //private_wifi for 5G
3738 {
3739 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3740 }
3741 else if(apIndex == 4) //public_wifi for 2.4G
3742 {
3743 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3744 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3745 {
3746 return RETURN_ERR;
3747 }
3748 if(buf[0] == '#')//tp-link
3749 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3750 else//tenda
3751 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3752 }
3753 else if(apIndex == 5) //public_wifi for 5G
3754 {
3755 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3756 }
3757
3758 GetIfacestatus(interface_name, interface_status);
3759
3760 if(0 != strcmp(interface_status, "1"))
3761 return RETURN_ERR;
3762
3763 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3764 system(cmd);
3765
3766 fp = fopen("/tmp/SSID_Stats.txt", "r");
3767 if(fp == NULL)
3768 {
3769 printf("/tmp/SSID_Stats.txt not exists \n");
3770 return RETURN_ERR;
3771 }
3772 fclose(fp);
3773
3774 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3775 File_Reading(buf, Value);
3776 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3777
3778 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3779 File_Reading(buf, Value);
3780 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3781
3782 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3783 File_Reading(buf, Value);
3784 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3785
3786 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3787 File_Reading(buf, Value);
3788 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3789
3790 /* There is no specific parameter from caller to associate the value wifi_Associations */
3791 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3792 //_syscmd(cmd, buf, sizeof(buf));
3793 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3794 }
3795#endif
3796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3797 return RETURN_OK;
3798}
3799
3800INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3801{
3802 char interface_name[MAX_BUF_SIZE] = {0};
3803 char interface_status[MAX_BUF_SIZE] = {0};
3804 char Value[MAX_BUF_SIZE] = {0};
3805 char buf[MAX_CMD_SIZE] = {0};
3806 char cmd[MAX_CMD_SIZE] = {0};
3807 FILE *fp = NULL;
3808
3809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3810 if (NULL == output_struct)
3811 return RETURN_ERR;
3812
3813 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3814
3815 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3816 {
3817 if(apIndex == 0) //private_wifi for 2.4G
3818 {
3819 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3820 }
3821 else if(apIndex == 1) //private_wifi for 5G
3822 {
3823 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3824 }
3825 else if(apIndex == 4) //public_wifi for 2.4G
3826 {
3827 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3828 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3829 {
3830 return RETURN_ERR;
3831 }
3832 if(buf[0] == '#')
3833 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3834 else
3835 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3836 }
3837 else if(apIndex == 5) //public_wifi for 5G
3838 {
3839 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3840 }
3841
3842 GetIfacestatus(interface_name, interface_status);
3843
3844 if(0 != strcmp(interface_status, "1"))
3845 return RETURN_ERR;
3846
3847 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3848 system(cmd);
3849
3850 fp = fopen("/tmp/SSID_Stats.txt", "r");
3851 if(fp == NULL)
3852 {
3853 printf("/tmp/SSID_Stats.txt not exists \n");
3854 return RETURN_ERR;
3855 }
3856 fclose(fp);
3857
3858 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3859 File_Reading(buf, Value);
3860 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3861
3862 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3863 File_Reading(buf, Value);
3864 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3865
3866 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3867 File_Reading(buf, Value);
3868 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3869
3870 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3871 File_Reading(buf, Value);
3872 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3873 }
3874
3875 output_struct->wifi_UnicastPacketsSent = 0;
3876 output_struct->wifi_UnicastPacketsReceived = 0;
3877 output_struct->wifi_MulticastPacketsSent = 0;
3878 output_struct->wifi_MulticastPacketsReceived = 0;
3879 output_struct->wifi_BroadcastPacketsSent = 0;
3880 output_struct->wifi_BroadcastPacketsRecevied = 0;
3881 output_struct->wifi_UnknownPacketsReceived = 0;
3882
3883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3884 return RETURN_OK;
3885}
3886
3887INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3888{
3889 INT status = RETURN_ERR;
3890
3891 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3892 //Below values should get updated from hal
3893 output_struct->wifi_RetransCount=0;
3894 output_struct->wifi_FailedRetransCount=0;
3895 output_struct->wifi_RetryCount=0;
3896 output_struct->wifi_MultipleRetryCount=0;
3897 output_struct->wifi_ACKFailureCount=0;
3898 output_struct->wifi_AggregatedPacketCount=0;
3899
3900 status = RETURN_OK;
3901 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3902
3903 return status;
3904}
3905
3906INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
3907{
3908 INT status = RETURN_ERR;
3909 UINT index;
3910 wifi_neighbor_ap_t *pt=NULL;
3911
3912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3913 *output_array_size=2;
3914 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
3915 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
3916 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
3917 strcpy(pt->ap_Radio,"");
3918 strcpy(pt->ap_SSID,"");
3919 strcpy(pt->ap_BSSID,"");
3920 strcpy(pt->ap_Mode,"");
3921 pt->ap_Channel=1;
3922 pt->ap_SignalStrength=0;
3923 strcpy(pt->ap_SecurityModeEnabled,"");
3924 strcpy(pt->ap_EncryptionMode,"");
3925 strcpy(pt->ap_OperatingFrequencyBand,"");
3926 strcpy(pt->ap_SupportedStandards,"");
3927 strcpy(pt->ap_OperatingStandards,"");
3928 strcpy(pt->ap_OperatingChannelBandwidth,"");
3929 pt->ap_BeaconPeriod=1;
3930 pt->ap_Noise=0;
3931 strcpy(pt->ap_BasicDataTransferRates,"");
3932 strcpy(pt->ap_SupportedDataTransferRates,"");
3933 pt->ap_DTIMPeriod=1;
3934 pt->ap_ChannelUtilization = 1;
3935 }
3936
3937 status = RETURN_OK;
3938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3939
3940 return status;
3941}
3942
3943//----------------- AP HAL -------------------------------
3944
3945//>> Deprecated: used for old RDKB code.
3946INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
3947{
3948 if (NULL == output_ulong || NULL == output_struct)
3949 return RETURN_ERR;
3950 *output_ulong = 0;
3951 *output_struct = NULL;
3952 return RETURN_OK;
3953}
3954
3955#ifdef HAL_NETLINK_IMPL
3956static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
3957 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3958 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3959 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
3960 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
3961 char mac_addr[20];
3962 static int count=0;
3963 int rate=0;
3964
3965 wifi_device_info_t *out = (wifi_device_info_t*)arg;
3966
3967 nla_parse(tb,
3968 NL80211_ATTR_MAX,
3969 genlmsg_attrdata(gnlh, 0),
3970 genlmsg_attrlen(gnlh, 0),
3971 NULL);
3972
3973 if(!tb[NL80211_ATTR_STA_INFO]) {
3974 fprintf(stderr, "sta stats missing!\n");
3975 return NL_SKIP;
3976 }
3977
3978
3979 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
3980 fprintf(stderr, "failed to parse nested attributes!\n");
3981 return NL_SKIP;
3982 }
3983
3984 //devIndex starts from 1
3985 if( ++count == out->wifi_devIndex )
3986 {
3987 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
3988 //Getting the mac addrress
3989 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
3990
3991 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
3992 fprintf(stderr, "failed to parse nested rate attributes!");
3993 return NL_SKIP;
3994 }
3995
3996 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
3997 if(rinfo[NL80211_RATE_INFO_BITRATE])
3998 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
3999 out->wifi_devTxRate = rate/10;
4000 }
4001
4002 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4003 fprintf(stderr, "failed to parse nested rate attributes!");
4004 return NL_SKIP;
4005 }
4006
4007 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4008 if(rinfo[NL80211_RATE_INFO_BITRATE])
4009 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4010 out->wifi_devRxRate = rate/10;
4011 }
4012 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4013 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4014
4015 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4016 count = 0; //starts the count for next cycle
4017 return NL_STOP;
4018 }
4019
4020 return NL_SKIP;
4021
4022}
4023#endif
4024
4025INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4026{
4027#ifdef HAL_NETLINK_IMPL
4028 Netlink nl;
4029 char if_name[10];
4030
4031 wifi_device_info_t info;
4032 info.wifi_devIndex = devIndex;
4033
4034 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4035
4036 nl.id = initSock80211(&nl);
4037
4038 if (nl.id < 0) {
4039 fprintf(stderr, "Error initializing netlink \n");
4040 return -1;
4041 }
4042
4043 struct nl_msg* msg = nlmsg_alloc();
4044
4045 if (!msg) {
4046 fprintf(stderr, "Failed to allocate netlink message.\n");
4047 nlfree(&nl);
4048 return -2;
4049 }
4050
4051 genlmsg_put(msg,
4052 NL_AUTO_PORT,
4053 NL_AUTO_SEQ,
4054 nl.id,
4055 0,
4056 NLM_F_DUMP,
4057 NL80211_CMD_GET_STATION,
4058 0);
4059
4060 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4061 nl_send_auto(nl.socket, msg);
4062 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4063 nl_recvmsgs(nl.socket, nl.cb);
4064 nlmsg_free(msg);
4065 nlfree(&nl);
4066
4067 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4068 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4069 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4070 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4071 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4072 return RETURN_OK;
4073#else
4074 //iw utility to retrieve station information
4075#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4076#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4077#define MACFILE "/tmp/wifi_AssoMac.txt"
4078#define TXRATEFILE "/tmp/wifi_txrate.txt"
4079#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4080 FILE *file = NULL;
4081 char if_name[10] = {'\0'};
4082 char pipeCmd[256] = {'\0'};
4083 char line[256];
4084 int count,device = 0;
4085
4086 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4087
4088 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4089 file = popen(pipeCmd, "r");
4090
4091 if(file == NULL)
4092 return RETURN_ERR; //popen failed
4093
4094 fgets(line, sizeof line, file);
4095 device = atoi(line);
4096 pclose(file);
4097
4098 if(device == 0)
4099 return RETURN_ERR; //No devices are connected
4100
4101 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4102 system(pipeCmd);
4103
4104 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4105
4106 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4107
4108 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4109
4110 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4111
4112 //devIndex starts from 1, ++count
4113 if((file = fopen(SIGNALFILE, "r")) != NULL )
4114 {
4115 for(count =0;fgets(line, sizeof line, file) != NULL;)
4116 {
4117 if (++count == devIndex)
4118 {
4119 output_struct->wifi_devSignalStrength = atoi(line);
4120 break;
4121 }
4122 }
4123 fclose(file);
4124 }
4125 else
4126 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4127
4128 if((file = fopen(MACFILE, "r")) != NULL )
4129 {
4130 for(count =0;fgets(line, sizeof line, file) != NULL;)
4131 {
4132 if (++count == devIndex)
4133 {
4134 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]);
4135 break;
4136 }
4137 }
4138 fclose(file);
4139 }
4140 else
4141 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4142
4143 if((file = fopen(TXRATEFILE, "r")) != NULL )
4144 {
4145 for(count =0;fgets(line, sizeof line, file) != NULL;)
4146 {
4147 if (++count == devIndex)
4148 {
4149 output_struct->wifi_devTxRate = atoi(line);
4150 break;
4151 }
4152 }
4153 fclose(file);
4154 }
4155 else
4156 fprintf(stderr,"fopen wifi_txrate.txt failed");
4157
4158 if((file = fopen(RXRATEFILE, "r")) != NULL)
4159 {
4160 for(count =0;fgets(line, sizeof line, file) != NULL;)
4161 {
4162 if (++count == devIndex)
4163 {
4164 output_struct->wifi_devRxRate = atoi(line);
4165 break;
4166 }
4167 }
4168 fclose(file);
4169 }
4170 else
4171 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4172
4173 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4174
4175 return RETURN_OK;
4176#endif
4177}
4178
4179INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4180{
4181 if (NULL == device)
4182 return RETURN_ERR;
4183 return RETURN_OK;
4184}
4185//<<
4186
4187
4188//--------------wifi_ap_hal-----------------------------
4189//enables CTS protection for the radio used by this AP
4190INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4191{
4192 //save config and Apply instantly
4193 return RETURN_ERR;
4194}
4195
4196// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4197INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4198{
developer463d39a2022-09-13 15:32:51 +08004199 char config_file[64] = {'\0'};
4200 char buf[64] = {'\0'};
4201 struct params list;
4202
4203 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4204 list.name = "ht_coex";
4205 snprintf(buf, sizeof(buf), "%d", enable);
4206 list.value = buf;
4207
4208 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4209 wifi_hostapdWrite(config_file, &list, 1);
4210 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4211
4212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4213
4214 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004215}
4216
4217//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4218INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4219{
developerea4bcce2022-09-13 15:26:13 +08004220 char config_file[MAX_BUF_SIZE] = {'\0'};
4221 char buf[MAX_BUF_SIZE] = {'\0'};
4222 struct params list;
4223
4224 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4225 if (threshold < 256 || threshold > 2346 )
4226 return RETURN_ERR;
4227 list.name = "fragm_threshold";
4228 snprintf(buf, sizeof(buf), "%d", threshold);
4229 list.value = buf;
4230
4231 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4232 wifi_hostapdWrite(config_file, &list, 1);
4233 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004234
developerea4bcce2022-09-13 15:26:13 +08004235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004236
4237 return RETURN_OK;
4238}
4239
4240// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4241INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4242{
developer51a927d2022-09-13 15:42:22 +08004243 char config_file[64] = {'\0'};
4244 char cmd[128] = {'\0'};
4245 char buf[64] = {'\0'};
4246 char stbc_config[16] = {'\0'};
4247 wifi_band band;
4248 int iterator = 0;
4249 BOOL current_stbc = FALSE;
4250
4251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4252
4253 band = wifi_index_to_band(radioIndex);
4254 if (band == band_invalid)
4255 return RETURN_ERR;
4256
4257 if (band == band_2_4)
4258 iterator = 1;
4259 else if (band == band_5)
4260 iterator = 2;
4261 else
4262 return RETURN_OK;
4263
4264 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4265
4266 // set ht and vht config
4267 for (int i = 0; i < iterator; i++) {
4268 memset(stbc_config, 0, sizeof(stbc_config));
4269 memset(cmd, 0, sizeof(cmd));
4270 memset(buf, 0, sizeof(buf));
4271 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4272 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4273 _syscmd(cmd, buf, sizeof(buf));
4274 if (strlen(buf) != 0)
4275 current_stbc = TRUE;
4276 if (current_stbc == STBC_Enable)
4277 continue;
4278
4279 if (STBC_Enable == TRUE) {
4280 // Append the STBC flags in capab config
4281 memset(cmd, 0, sizeof(cmd));
4282 if (i == 0)
4283 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4284 else
4285 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4286 _syscmd(cmd, buf, sizeof(buf));
4287 } else if (STBC_Enable == FALSE) {
4288 // Remove the STBC flags and remain other flags in capab
4289 memset(cmd, 0, sizeof(cmd));
4290 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4291 _syscmd(cmd, buf, sizeof(buf));
4292 memset(cmd, 0, sizeof(cmd));
4293 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4294 _syscmd(cmd, buf, sizeof(buf));
4295 }
4296 }
4297
4298 wifi_reloadAp(radioIndex);
4299
4300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4301 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004302}
4303
4304// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4305INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4306{
4307 return RETURN_ERR;
4308}
4309
4310// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4311INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4312{
4313 //Apply instantly
4314 return RETURN_ERR;
4315}
4316
4317//P2 // outputs the number of Tx streams
4318INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4319{
4320 return RETURN_ERR;
4321}
4322
4323//P2 // sets the number of Tx streams to an enviornment variable
4324INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4325{
4326 //save to wifi config, wait for wifi reset or wifi_pushTxChainMask to apply
4327 return RETURN_ERR;
4328}
4329
4330//P2 // outputs the number of Rx streams
4331INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4332{
4333 if (NULL == output_int)
4334 return RETURN_ERR;
4335 *output_int = 1;
4336 return RETURN_OK;
4337}
4338
4339//P2 // sets the number of Rx streams to an enviornment variable
4340INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4341{
4342 //save to wifi config, wait for wifi reset or wifi_pushRxChainMask to apply
4343 return RETURN_ERR;
4344}
4345
4346//Get radio RDG enable setting
4347INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4348{
4349 if (NULL == output_bool)
4350 return RETURN_ERR;
4351 *output_bool = TRUE;
4352 return RETURN_OK;
4353}
4354
4355//Get radio RDG enable setting
4356INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4357{
4358 if (NULL == output_bool)
4359 return RETURN_ERR;
4360 *output_bool = TRUE;
4361 return RETURN_OK;
4362}
4363
4364//Set radio RDG enable setting
4365INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4366{
4367 return RETURN_ERR;
4368}
4369
4370//Get radio ADDBA enable setting
4371INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4372{
4373 if (NULL == output_bool)
4374 return RETURN_ERR;
4375 *output_bool = TRUE;
4376 return RETURN_OK;
4377}
4378
4379//Set radio ADDBA enable setting
4380INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4381{
4382 return RETURN_ERR;
4383}
4384
4385//Get radio auto block ack enable setting
4386INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4387{
4388 if (NULL == output_bool)
4389 return RETURN_ERR;
4390 *output_bool = TRUE;
4391 return RETURN_OK;
4392}
4393
4394//Set radio auto block ack enable setting
4395INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4396{
4397 return RETURN_ERR;
4398}
4399
4400//Get radio 11n pure mode enable support
4401INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4402{
4403 if (NULL == output_bool)
4404 return RETURN_ERR;
4405 *output_bool = TRUE;
4406 return RETURN_OK;
4407}
4408
4409//Get radio 11n pure mode enable setting
4410INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4411{
4412 if (NULL == output_bool)
4413 return RETURN_ERR;
4414 *output_bool = TRUE;
4415 return RETURN_OK;
4416}
4417
4418//Set radio 11n pure mode enable setting
4419INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4420{
4421 return RETURN_ERR;
4422}
4423
4424//Get radio IGMP snooping enable setting
4425INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4426{
developer81bf2ed2022-09-13 15:31:14 +08004427 char cmd[128]={0};
4428 char buf[4]={0};
4429 bool bridge = FALSE, mac80211 = FALSE;
4430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4431
4432 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004433 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004434
4435 *output_bool = FALSE;
4436
4437 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4438 _syscmd(cmd, buf, sizeof(buf));
4439 if (strncmp(buf, "1", 1) == 0)
4440 bridge = TRUE;
4441
4442 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4443 _syscmd(cmd, buf, sizeof(buf));
4444 if (strncmp(buf, "1", 1) == 0)
4445 mac80211 = TRUE;
4446
4447 if (bridge && mac80211)
4448 *output_bool = TRUE;
4449
4450 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004451 return RETURN_OK;
4452}
4453
4454//Set radio IGMP snooping enable setting
4455INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4456{
developer81bf2ed2022-09-13 15:31:14 +08004457 char cmd[128]={0};
4458 char buf[4]={0};
4459
4460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4461
4462 // bridge
4463 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4464 _syscmd(cmd, buf, sizeof(buf));
4465
4466 // mac80211
4467 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4468 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4469 _syscmd(cmd, buf, sizeof(buf));
4470 }
4471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4472 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004473}
4474
4475//Get the Reset count of radio
4476INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4477{
4478 if (NULL == output_int)
4479 return RETURN_ERR;
4480 *output_int = (radioIndex==0)? 1: 3;
4481
4482 return RETURN_OK;
4483}
4484
4485
4486//---------------------------------------------------------------------------------------------------
4487//
4488// Additional Wifi AP level APIs used for Access Point devices
4489//
4490//---------------------------------------------------------------------------------------------------
4491
4492// creates a new ap and pushes these parameters to the hardware
4493INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4494{
4495 char buf[1024];
4496 char cmd[128];
4497
4498 if (NULL == essid)
4499 return RETURN_ERR;
4500
4501 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4502 _syscmd(cmd, buf, sizeof(buf));
4503
4504 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4505 _syscmd(cmd, buf, sizeof(buf));
4506
4507 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4508
4509 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4510 _syscmd(cmd, buf, sizeof(buf));
4511
4512 return RETURN_OK;
4513}
4514
4515// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4516INT wifi_deleteAp(INT apIndex)
4517{
4518 char buf[1024];
4519 char cmd[128];
4520
4521 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4522 _syscmd(cmd, buf, sizeof(buf));
4523
4524 wifi_removeApSecVaribles(apIndex);
4525
4526 return RETURN_OK;
4527}
4528
4529// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4530INT wifi_getApName(INT apIndex, CHAR *output_string)
4531{
4532 if(NULL == output_string)
4533 return RETURN_ERR;
4534
4535 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4536 return RETURN_OK;
4537}
4538
4539// Outputs the index number in that corresponds to the SSID string
4540INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4541{
4542 CHAR *pos = NULL;
4543
4544 *output_int = -1;
4545 pos = strstr(inputSsidString, AP_PREFIX);
4546 if(pos)
4547 {
4548 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4549 return RETURN_OK;
4550 }
4551 return RETURN_ERR;
4552}
4553
4554INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4555{
4556 return wifi_getIndexFromName(inputSsidString, output_int);
4557}
4558
4559// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4560INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4561{
4562 char buf[MAX_BUF_SIZE] = {0};
4563 char cmd[MAX_CMD_SIZE] = {0};
4564 char config_file[MAX_BUF_SIZE] = {0};
4565
4566 if(NULL == output_string)
4567 return RETURN_ERR;
4568
4569 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4570 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4571 if((strcmp(buf,"3")==0))
4572 snprintf(output_string, 32, "WPAand11i");
4573 else if((strcmp(buf,"2")==0))
4574 snprintf(output_string, 32, "11i");
4575 else if((strcmp(buf,"1")==0))
4576 snprintf(output_string, 32, "WPA");
4577 else
4578 snprintf(output_string, 32, "None");
4579
4580 return RETURN_OK;
4581}
4582
4583// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4584INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4585{
4586 char config_file[MAX_BUF_SIZE] = {0};
4587 struct params list;
4588
4589 if (NULL == beaconTypeString)
4590 return RETURN_ERR;
4591 list.name = "wpa";
4592 list.value = "0";
4593
4594 if((strcmp(beaconTypeString,"WPAand11i")==0))
4595 list.value="3";
4596 else if((strcmp(beaconTypeString,"11i")==0))
4597 list.value="2";
4598 else if((strcmp(beaconTypeString,"WPA")==0))
4599 list.value="1";
4600
4601 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4602 wifi_hostapdWrite(config_file, &list, 1);
4603 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4604 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4605 return RETURN_OK;
4606}
4607
4608// sets the beacon interval on the hardware for this AP
4609INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4610{
developer5f222492022-09-13 15:21:52 +08004611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4612 struct params params={'\0'};
4613 char buf[MAX_BUF_SIZE] = {'\0'};
4614 char config_file[MAX_BUF_SIZE] = {'\0'};
4615
4616 params.name = "beacon_int";
4617 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4618 params.value = buf;
4619
4620 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4621 wifi_hostapdWrite(config_file, &params, 1);
4622
4623 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4624 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4625 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004626}
4627
4628INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4629{
4630 //save config and apply instantly
4631 return RETURN_ERR;
4632}
4633
4634// Get the packet size threshold supported.
4635INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4636{
4637 //save config and apply instantly
4638 if (NULL == output_bool)
4639 return RETURN_ERR;
4640 *output_bool = FALSE;
4641 return RETURN_OK;
4642}
4643
4644// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4645INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4646{
4647 char cmd[128];
4648 char buf[512];
4649
4650 if (threshold > 0)
4651 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4652 else
4653 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4654 _syscmd(cmd, buf, sizeof(buf));
4655
4656 return RETURN_OK;
4657}
4658
4659// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4660INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4661{
4662 if (NULL == output_string)
4663 return RETURN_ERR;
4664 snprintf(output_string, 32, "TKIPandAESEncryption");
4665 return RETURN_OK;
4666
4667}
4668
4669// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4670INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4671{
4672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4673 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4674
4675 if(NULL == output_string)
4676 return RETURN_ERR;
4677
4678 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4679 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4680
4681 if(strcmp(buf,"0")==0)
4682 {
4683 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4684 snprintf(output_string, 32, "None");
4685 return RETURN_OK;
4686 }
4687 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4688 param_name = "rsn_pairwise";
4689 else if((strcmp(buf,"1")==0))
4690 param_name = "wpa_pairwise";
4691 else
4692 return RETURN_ERR;
4693 memset(output_string,'\0',32);
4694 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4695 wifi_hostapdRead(config_file,param_name,output_string,32);
4696 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4697
4698 if(strcmp(output_string,"TKIP") == 0)
4699 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4700 else if(strcmp(output_string,"CCMP") == 0)
4701 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4702 else if(strcmp(output_string,"TKIP CCMP") == 0)
4703 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4704
4705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4706 return RETURN_OK;
4707}
4708
4709// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4710INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4711{
4712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4713 struct params params={'\0'};
4714 char output_string[32];
4715 char config_file[MAX_BUF_SIZE] = {0};
4716
4717 memset(output_string,'\0',32);
4718 wifi_getApWpaEncryptionMode(apIndex,output_string);
4719
4720 if(strcmp(encMode, "TKIPEncryption") == 0)
4721 params.value = "TKIP";
4722 else if(strcmp(encMode,"AESEncryption") == 0)
4723 params.value = "CCMP";
4724 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4725 params.value = "TKIP CCMP";
4726
4727 if((strcmp(output_string,"WPAand11i")==0))
4728 {
4729 params.name = "wpa_pairwise";
4730 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4731 wifi_hostapdWrite(config_file, &params, 1);
4732 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4733
4734 params.name,"rsn_pairwise";
4735 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4736 wifi_hostapdWrite(config_file, &params, 1);
4737 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4738
4739 return RETURN_OK;
4740 }
4741 else if((strcmp(output_string,"11i")==0))
4742 {
4743 params.name = "rsn_pairwise";
4744 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4745 wifi_hostapdWrite(config_file, &params, 1);
4746 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4747 return RETURN_OK;
4748 }
4749 else if((strcmp(output_string,"WPA")==0))
4750 {
4751 params.name = "wpa_pairwise";
4752 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4753 wifi_hostapdWrite(config_file, &params, 1);
4754 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4755 return RETURN_OK;
4756 }
4757
4758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4759 return RETURN_OK;
4760}
4761
4762// deletes internal security varable settings for this ap
4763INT wifi_removeApSecVaribles(INT apIndex)
4764{
4765 //TODO: remove the entry in hostapd config file
4766 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4767 //_syscmd(cmd, buf, sizeof(buf));
4768
4769 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4770 //_syscmd(cmd, buf, sizeof(buf));
4771 return RETURN_ERR;
4772}
4773
4774// changes the hardware settings to disable encryption on this ap
4775INT wifi_disableApEncryption(INT apIndex)
4776{
4777 //Apply instantly
4778 return RETURN_ERR;
4779}
4780
4781// set the authorization mode on this ap
4782// mode mapping as: 1: open, 2: shared, 4:auto
4783INT wifi_setApAuthMode(INT apIndex, INT mode)
4784{
4785 //Apply instantly
4786 return RETURN_ERR;
4787}
4788
4789// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4790INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4791{
4792 //save to wifi config, and wait for wifi restart to apply
4793 struct params params={'\0'};
4794 char config_file[MAX_BUF_SIZE] = {0};
4795 int ret;
4796
4797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4798 if(authMode == NULL)
4799 return RETURN_ERR;
4800
4801 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4802 params.name = "wpa_key_mgmt";
4803
4804 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4805 params.value = "WPA-PSK";
4806 else if(strcmp(authMode,"EAPAuthentication") == 0)
4807 params.value = "WPA-EAP";
4808 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4809 return RETURN_OK; //This is taken careof in beaconType
4810
4811 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4812 ret=wifi_hostapdWrite(config_file,&params,1);
4813 if(!ret)
4814 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
4815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4816
4817 return ret;
4818}
4819
4820// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4821INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4822{
4823 //save to wifi config, and wait for wifi restart to apply
4824 char BeaconType[50] = {0};
4825 char config_file[MAX_BUF_SIZE] = {0};
4826
4827 *authMode = 0;
4828 wifi_getApBeaconType(apIndex,BeaconType);
4829 printf("%s____%s \n",__FUNCTION__,BeaconType);
4830
4831 if(strcmp(BeaconType,"None") == 0)
4832 strcpy(authMode,"None");
4833 else
4834 {
4835 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4836 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
4837 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
4838 if(strcmp(authMode,"WPA-PSK") == 0)
4839 strcpy(authMode,"SharedAuthentication");
4840 else if(strcmp(authMode,"WPA-EAP") == 0)
4841 strcpy(authMode,"EAPAuthentication");
4842 }
4843
4844 return RETURN_OK;
4845}
4846
4847// Outputs the number of stations associated per AP
4848INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
4849{
4850 char cmd[128]={0};
4851 char buf[128]={0};
4852 BOOL status = false;
4853
4854 if(apIndex > MAX_APS)
4855 return RETURN_ERR;
4856
4857 wifi_getApEnable(apIndex,&status);
4858 if (!status)
4859 return RETURN_OK;
4860
4861 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
4862 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
4863 _syscmd(cmd, buf, sizeof(buf));
4864 sscanf(buf,"%lu", output_ulong);
4865
4866 return RETURN_OK;
4867}
4868
4869// manually removes any active wi-fi association with the device specified on this ap
4870INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
4871{
4872 char buf[126]={'\0'};
4873
4874 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
4875 system(buf);
4876
4877 return RETURN_OK;
4878}
4879
4880// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
4881INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
4882{
4883 if(NULL == output_int)
4884 return RETURN_ERR;
4885 *output_int = apIndex%2;
4886 return RETURN_OK;
4887}
4888
4889// sets the radio index for the specific ap
4890INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
4891{
4892 //set to config only and wait for wifi reset to apply settings
4893 return RETURN_ERR;
4894}
4895
4896// Get the ACL MAC list per AP
4897INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4898{
4899 char cmd[MAX_CMD_SIZE]={'\0'};
4900 int ret = 0;
4901
4902 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4903 ret = _syscmd(cmd,macArray,buf_size);
4904 if (ret != 0)
4905 return RETURN_ERR;
4906
4907 return RETURN_OK;
4908}
4909
developere6aafda2022-09-13 14:59:28 +08004910INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
4911{
4912 char cmd[MAX_CMD_SIZE]={'\0'};
4913 int ret = 0;
4914
4915 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
4916 ret = _syscmd(cmd,macArray,buf_size);
4917 if (ret != 0)
4918 return RETURN_ERR;
4919
4920 return RETURN_OK;
4921}
4922
4923
developer06a01d92022-09-07 16:32:39 +08004924// Get the list of stations associated per AP
4925INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
4926{
4927 char cmd[128];
4928
4929 if(apIndex > 3) //Currently supporting apIndex upto 3
4930 return RETURN_ERR;
4931 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
4932 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
4933 _syscmd(cmd, macArray, buf_size);
4934
4935 return RETURN_OK;
4936}
4937
4938// adds the mac address to the filter list
4939//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4940INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4941{
4942 char cmd[MAX_CMD_SIZE]={'\0'};
4943 char buf[MAX_BUF_SIZE]={'\0'};
4944
4945#if 0
4946 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4947 if(_syscmd(cmd,buf,sizeof(buf)))
4948 return RETURN_ERR;
4949#endif
4950 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
4951 if(_syscmd(cmd,buf,sizeof(buf)))
4952 return RETURN_ERR;
4953
4954 return RETURN_OK;
4955}
4956
4957// deletes the mac address from the filter list
4958//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
4959INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
4960{
4961 char cmd[MAX_CMD_SIZE]={'\0'};
4962 char buf[MAX_BUF_SIZE]={'\0'};
4963
4964#if 0
4965 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
4966 if(_syscmd(cmd,buf,sizeof(buf)))
4967 return RETURN_ERR;
4968
4969#endif
4970 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
4971 if(_syscmd(cmd,buf,sizeof(buf)))
4972 return RETURN_ERR;
4973
4974 return RETURN_OK;
4975}
4976
4977// outputs the number of devices in the filter list
4978INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
4979{
developere6aafda2022-09-13 14:59:28 +08004980 char cmd[MAX_BUF_SIZE]={0};
4981 char buf[MAX_CMD_SIZE]={0};
4982
4983 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4984 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08004985 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08004986
4987 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
4988 _syscmd(cmd, buf, sizeof(buf));
4989
4990 *output_uint = atoi(buf);
4991
4992 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4993 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004994}
4995
4996INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
4997{
4998 char cmd[128]={'\0'};
4999 char buf[128]={'\0'};
5000
5001 if(strcmp(action,"DENY")==0)
5002 {
5003 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5004 system(buf);
5005 return RETURN_OK;
5006 }
5007
5008 if(strcmp(action,"ALLOW")==0)
5009 {
5010 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5011 system(buf);
5012 return RETURN_OK;
5013 }
5014
5015 return RETURN_ERR;
5016
5017}
5018
5019// enable kick for devices on acl black list
5020INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5021{
5022 char aclArray[512] = {0}, *acl = NULL;
5023 char assocArray[512] = {0}, *asso = NULL;
5024
developere6aafda2022-09-13 14:59:28 +08005025 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005026 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5027
5028 // if there are no devices connected there is nothing to do
5029 if (strlen(assocArray) < 17)
5030 return RETURN_OK;
5031
5032 if (enable == TRUE)
5033 {
5034 //kick off the MAC which is in ACL array (deny list)
5035 acl = strtok(aclArray, "\r\n");
5036 while (acl != NULL) {
5037 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5038 wifi_kickApAssociatedDevice(apIndex, acl);
5039
5040 acl = strtok(NULL, "\r\n");
5041 }
developere6aafda2022-09-13 14:59:28 +08005042 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005043 }
5044 else
5045 {
developere6aafda2022-09-13 14:59:28 +08005046 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005047 }
5048
5049#if 0
5050 //TODO: need to revisit below implementation
5051 char aclArray[512]={0}, *acl=NULL;
5052 char assocArray[512]={0}, *asso=NULL;
5053 char buf[256]={'\0'};
5054 char action[10]={'\0'};
5055 FILE *fr=NULL;
5056 char interface[10]={'\0'};
5057 char config_file[MAX_BUF_SIZE] = {0};
5058
5059 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5060 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5061 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5062 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5063
5064 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5065 system(buf);
5066 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5067 system(buf);
5068 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5069 system(buf);
5070 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5071 system(buf);
5072 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5073 system(buf);
5074
5075 if ( enable == TRUE )
5076 {
5077 int device_count=0;
5078 strcpy(action,"DENY");
5079 //kick off the MAC which is in ACL array (deny list)
5080 acl = strtok (aclArray,",");
5081 while (acl != NULL) {
5082 if(strlen(acl)>=17)
5083 {
5084 apply_rules(apIndex, acl,action,interface);
5085 device_count++;
5086 //Register mac to be blocked ,in syscfg.db persistent storage
5087 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5088 system(buf);
5089 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5090 system(buf);
5091 system("syscfg commit");
5092
5093 wifi_kickApAssociatedDevice(apIndex, acl);
5094 }
5095 acl = strtok (NULL, ",");
5096 }
5097 }
5098 else
5099 {
5100 int device_count=0;
5101 char cmdmac[20]={'\0'};
5102 strcpy(action,"ALLOW");
5103 //kick off the MAC which is not in ACL array (allow list)
5104 acl = strtok (aclArray,",");
5105 while (acl != NULL) {
5106 if(strlen(acl)>=17)
5107 {
5108 apply_rules(apIndex, acl,action,interface);
5109 device_count++;
5110 //Register mac to be Allowed ,in syscfg.db persistent storage
5111 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5112 system(buf);
5113 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5114 system(buf);
5115 sprintf(cmdmac,"%s",acl);
5116 }
5117 acl = strtok (NULL, ",");
5118 }
5119 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5120 system(buf);
5121
5122 //Disconnect the mac which is not in ACL
5123 asso = strtok (assocArray,",");
5124 while (asso != NULL) {
5125 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5126 wifi_kickApAssociatedDevice(apIndex, asso);
5127 asso = strtok (NULL, ",");
5128 }
5129 }
5130#endif
5131 return RETURN_OK;
5132}
5133
5134INT wifi_setPreferPrivateConnection(BOOL enable)
5135{
5136 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5137 char buf[1024] = {0};
5138
5139 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5140 if(enable == TRUE)
5141 {
5142 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5143 sprintf(buf,"ifconfig %s down" ,interface_name);
5144 system(buf);
5145 memset(buf,0,sizeof(buf));
5146 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5147 sprintf(buf,"ifconfig %s down" ,interface_name);
5148 system(buf);
5149 }
5150 else
5151 {
5152 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5153 if(strcmp(ssid_cur_value,"1") == 0)
5154 wifi_RestartPrivateWifi_5G();
5155 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5156 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5157 if(strcmp(ssid_cur_value,"1") == 0)
5158 wifi_RestartHostapd_2G();
5159 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5160 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5161 if(strcmp(ssid_cur_value,"1") == 0)
5162 wifi_RestartHostapd_5G();
5163 }
5164 return RETURN_OK;
5165}
5166
5167// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5168INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5169{
5170 int items = 1;
5171 struct params list[2];
5172 char buf[MAX_BUF_SIZE] = {0};
5173 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005174 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005175
5176 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005177
developer10adcc12022-09-13 14:39:17 +08005178 if (filterMode == 0) {
5179 sprintf(buf, "%d", 0);
5180 list[0].value = buf;
5181
5182 char cmd[128], rtn[128];
5183 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5184 _syscmd(cmd, rtn, sizeof(rtn));
5185 memset(cmd,0,sizeof(cmd));
5186 // Delete deny_mac_file in hostapd configuration
5187 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5188 _syscmd(cmd, rtn, sizeof(rtn));
5189 }
5190 else if (filterMode == 1) {
5191 sprintf(buf, "%d", filterMode);
5192 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005193 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5194 list[1].name = "accept_mac_file";
5195 list[1].value = acl_file;
5196 items = 2;
developer10adcc12022-09-13 14:39:17 +08005197 } else if (filterMode == 2) {
5198 //TODO: deny_mac_file
5199 sprintf(buf, "%d", 0);
5200 list[0].value = buf;
5201 list[1].name = "deny_mac_file";
5202 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5203 list[1].value = deny_file;
5204 items = 2;
5205 } else {
5206 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005207 }
developer10adcc12022-09-13 14:39:17 +08005208
developer06a01d92022-09-07 16:32:39 +08005209 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5210 wifi_hostapdWrite(config_file, list, items);
5211
5212 return RETURN_OK;
5213
5214#if 0
5215 if(apIndex==0 || apIndex==1)
5216 {
5217 //set the filtermode
5218 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5219 system(buf);
5220 system("syscfg commit");
5221
5222 if(filterMode==0)
5223 {
5224 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5225 system(buf);
5226 return RETURN_OK;
5227 }
5228 }
5229 return RETURN_OK;
5230#endif
5231}
5232
5233// 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.
5234INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5235{
5236 return RETURN_ERR;
5237}
5238
5239// gets the vlan ID for this ap from an internal enviornment variable
5240INT wifi_getApVlanID(INT apIndex, INT *output_int)
5241{
5242 if(apIndex=0)
5243 {
5244 *output_int=100;
5245 return RETURN_OK;
5246 }
5247
5248 return RETURN_ERR;
5249}
5250
5251// sets the vlan ID for this ap to an internal enviornment variable
5252INT wifi_setApVlanID(INT apIndex, INT vlanId)
5253{
5254 //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)
5255 return RETURN_ERR;
5256}
5257
5258// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5259INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5260{
5261 snprintf(bridgeName, 32, "brlan0");
5262 snprintf(IP, 32, "10.0.0.1");
5263 snprintf(subnet, 32, "255.255.255.0");
5264
5265 return RETURN_OK;
5266}
5267
5268//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5269INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5270{
5271 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5272 return RETURN_ERR;
5273}
5274
5275// reset the vlan configuration for this ap
5276INT wifi_resetApVlanCfg(INT apIndex)
5277{
developerf5fef612022-09-20 19:38:26 +08005278 char original_config_file[64] = {0};
5279 char current_config_file[64] = {0};
5280 char buf[64] = {0};
5281 char cmd[64] = {0};
5282 char vlan_file[64] = {0};
5283 char vlan_tagged_interface[16] = {0};
5284 char vlan_bridge[16] = {0};
5285 char vlan_naming[16] = {0};
5286 struct params list[4] = {0};
5287 wifi_band band;
5288
5289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5290
5291 band = wifi_index_to_band(apIndex);
5292 if (band == band_2_4)
5293 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5294 else if (band = band_5)
5295 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5296 else if (band = band_6)
5297 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5298
5299 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5300
5301 if (strlen(vlan_file) == 0)
5302 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005303
developerf5fef612022-09-20 19:38:26 +08005304 // The file should exist or this vap would not work.
5305 if (access(vlan_file, F_OK) != 0) {
5306 sprintf(cmd, "touch %s", vlan_file);
5307 _syscmd(cmd, buf, sizeof(buf));
5308 }
5309 list[0].name = "vlan_file";
5310 list[0].value = vlan_file;
5311
5312 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5313 list[1].name = "vlan_tagged_interface";
5314 list[1].value = vlan_tagged_interface;
5315
5316 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5317 list[2].name = "vlan_bridge";
5318 list[2].value = vlan_bridge;
5319
5320 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5321 list[3].name = "vlan_naming";
5322 list[3].value = vlan_naming;
5323
5324 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5325 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005326 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005327 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005328
developerf5fef612022-09-20 19:38:26 +08005329 // restart this ap
5330 wifi_setApEnable(apIndex, FALSE);
5331 wifi_setApEnable(apIndex, TRUE);
5332
5333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5334
5335 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005336}
5337
5338// 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.
5339INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5340{
5341 return RETURN_ERR;
5342}
5343
5344// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5345INT wifi_startHostApd()
5346{
5347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5348 system("systemctl start hostapd.service");
5349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5350 return RETURN_OK;
5351 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5352}
5353
5354// stops hostapd
5355INT wifi_stopHostApd()
5356{
5357 char cmd[128] = {0};
5358 char buf[128] = {0};
5359
5360 sprintf(cmd,"systemctl stop hostapd");
5361 _syscmd(cmd, buf, sizeof(buf));
5362
5363 return RETURN_OK;
5364}
5365
5366// restart hostapd dummy function
5367INT wifi_restartHostApd()
5368{
5369 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5370 system("systemctl restart hostapd-global");
5371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5372
5373 return RETURN_OK;
5374}
5375
5376static int align_hostapd_config(int index)
5377{
5378 ULONG lval;
5379 wifi_getRadioChannel(index%2, &lval);
5380 wifi_setRadioChannel(index%2, lval);
5381}
5382
5383// sets the AP enable status variable for the specified ap.
5384INT wifi_setApEnable(INT apIndex, BOOL enable)
5385{
5386 char config_file[MAX_BUF_SIZE] = {0};
5387 char cmd[MAX_CMD_SIZE] = {0};
5388 char buf[MAX_BUF_SIZE] = {0};
5389 BOOL status;
5390
5391 wifi_getApEnable(apIndex,&status);
5392 if (enable == status)
5393 return RETURN_OK;
5394
5395 if (enable == TRUE) {
5396 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5397 align_hostapd_config(apIndex);
5398 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5399 //Hostapd will bring up this interface
5400 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5401 _syscmd(cmd, buf, sizeof(buf));
5402 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5403 _syscmd(cmd, buf, sizeof(buf));
5404 }
5405 else {
5406 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5407 _syscmd(cmd, buf, sizeof(buf));
5408 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5409 _syscmd(cmd, buf, sizeof(buf));
5410 }
5411 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5412 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5413 _syscmd(cmd, buf, sizeof(buf));
5414 //Wait for wifi up/down to apply
5415 return RETURN_OK;
5416}
5417
5418// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5419INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5420{
5421 char cmd[MAX_CMD_SIZE] = {'\0'};
5422 char buf[MAX_BUF_SIZE] = {'\0'};
5423
5424 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5425 return RETURN_ERR;
5426
5427 *output_bool = 0;
5428
5429 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5430 {
developer70490032022-09-13 15:45:20 +08005431 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005432 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5433 }
5434
5435 return RETURN_OK;
5436}
5437
5438// Outputs the AP "Enabled" "Disabled" status from driver
5439INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5440{
5441 char cmd[128] = {0};
5442 char buf[128] = {0};
5443 BOOL output_bool;
5444
5445 if ( NULL == output_string)
5446 return RETURN_ERR;
5447 wifi_getApEnable(apIndex,&output_bool);
5448
5449 if(output_bool == 1)
5450 snprintf(output_string, 32, "Up");
5451 else
5452 snprintf(output_string, 32, "Disable");
5453
5454 return RETURN_OK;
5455}
5456
5457//Indicates whether or not beacons include the SSID name.
5458// outputs a 1 if SSID on the AP is enabled, else outputs 0
5459INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5460{
5461 //get the running status
5462 char config_file[MAX_BUF_SIZE] = {0};
5463 char buf[16] = {0};
5464
5465 if (!output)
5466 return RETURN_ERR;
5467
5468 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5469 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5470 *output = (strncmp("0",buf,1) == 0);
5471
5472 return RETURN_OK;
5473}
5474
5475// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5476INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5477{
5478 //store the config, apply instantly
5479 char config_file[MAX_BUF_SIZE] = {0};
5480 struct params list;
5481
5482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5483 list.name = "ignore_broadcast_ssid";
5484 list.value = enable?"0":"1";
5485
5486 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5487 wifi_hostapdWrite(config_file, &list, 1);
5488 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5489 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005490 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005491 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5492
5493 return RETURN_OK;
5494}
5495
5496//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5497INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5498{
5499 //get the running status
5500 if(!output_uint)
5501 return RETURN_ERR;
5502 *output_uint=16;
5503 return RETURN_OK;
5504}
5505
5506INT wifi_setApRetryLimit(INT apIndex, UINT number)
5507{
5508 //apply instantly
5509 return RETURN_ERR;
5510}
5511
5512//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5513INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5514{
5515 if(!output)
5516 return RETURN_ERR;
5517 *output=TRUE;
5518 return RETURN_OK;
5519}
5520
5521//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5522INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5523{
5524 //get the running status from driver
5525 if(!output)
5526 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005527
5528 char config_file[MAX_BUF_SIZE] = {0};
5529 char buf[16] = {0};
5530
5531 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5532 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5533 if (strncmp("1",buf,1) == 0)
5534 *output = TRUE;
5535 else
5536 *output = FALSE;
5537
developer06a01d92022-09-07 16:32:39 +08005538 return RETURN_OK;
5539}
5540
5541//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5542INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5543{
5544 //get the running status from driver
5545 if(!output)
5546 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005547
5548 char config_file[MAX_BUF_SIZE] = {0};
5549 char buf[16] = {0};
5550
5551 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5552 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5553 if (strncmp("1",buf,1) == 0)
5554 *output = TRUE;
5555 else
5556 *output = FALSE;
5557
developer06a01d92022-09-07 16:32:39 +08005558 return RETURN_OK;
5559}
5560
5561// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5562INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5563{
5564 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005565 char config_file[MAX_BUF_SIZE] = {0};
5566 struct params list;
5567
5568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5569 list.name = "wmm_enabled";
5570 list.value = enable?"1":"0";
5571
5572 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5573 wifi_hostapdWrite(config_file, &list, 1);
5574 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5575 wifi_reloadAp(apIndex);
5576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5577
5578 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005579}
5580
5581//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.
5582INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5583{
5584 //get the running status from driver
5585 if(!output)
5586 return RETURN_ERR;
5587 *output=TRUE;
5588 return RETURN_OK;
5589}
5590
5591// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5592INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5593{
5594 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005595 char config_file[MAX_BUF_SIZE] = {0};
5596 struct params list;
5597
5598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5599 list.name = "uapsd_advertisement_enabled";
5600 list.value = enable?"1":"0";
5601
5602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5603 wifi_hostapdWrite(config_file, &list, 1);
5604 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5605 wifi_reloadAp(apIndex);
5606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5607
5608 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005609}
5610
5611// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5612INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5613{
5614 //save config and apply instantly.
5615 return RETURN_ERR;
5616}
5617
5618//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.
5619INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5620{
5621 //get the running status from driver
5622 if(!output_uint)
5623 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005624
5625 char output[16]={'\0'};
5626 char config_file[MAX_BUF_SIZE] = {0};
5627
5628 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5629 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5630 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5631 else {
5632 int device_num = atoi(output);
5633 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5634 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5635 return RETURN_ERR;
5636 }
5637 else {
5638 *output_uint = device_num;
5639 }
5640 }
5641
developer06a01d92022-09-07 16:32:39 +08005642 return RETURN_OK;
5643}
5644
5645INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5646{
5647 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005648 char str[MAX_BUF_SIZE]={'\0'};
5649 char cmd[MAX_CMD_SIZE]={'\0'};
5650 struct params params;
5651 char config_file[MAX_BUF_SIZE] = {0};
5652
5653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5654 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5655 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5656 return RETURN_ERR;
5657 }
5658 sprintf(str, "%d", number);
5659 params.name = "max_num_sta";
5660 params.value = str;
5661
5662 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5663 int ret = wifi_hostapdWrite(config_file, &params, 1);
5664 if (ret) {
5665 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5666 ,__func__, ret);
5667 }
5668
5669 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5670 if (ret) {
5671 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5672 ,__func__, ret);
5673 }
5674 wifi_reloadAp(apIndex);
5675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5676
5677 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005678}
5679
5680//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.
5681INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5682{
5683 //get the current threshold
5684 if(!output_uint)
5685 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005686 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5687 if (*output_uint == 0)
5688 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005689 return RETURN_OK;
5690}
5691
5692INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5693{
5694 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005695 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5696 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005697 return RETURN_ERR;
5698}
5699
5700//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.
5701INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5702{
5703 if(!output_uint)
5704 return RETURN_ERR;
5705 *output_uint = 3;
5706 return RETURN_OK;
5707}
5708
5709//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5710INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5711{
5712 if(!output_uint)
5713 return RETURN_ERR;
5714 *output_uint = 3;
5715 return RETURN_OK;
5716}
5717
5718//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.
5719INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5720{
5721 if(!output_in_seconds)
5722 return RETURN_ERR;
5723 *output_in_seconds = 0;
5724 return RETURN_OK;
5725}
5726
5727//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
5728INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5729{
5730 if(!output || apIndex>=MAX_APS)
5731 return RETURN_ERR;
5732 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
5733 snprintf(output, 128, "None,WPA2-Personal");
5734 return RETURN_OK;
5735}
5736
5737//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5738INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5739{
5740 char config_file[MAX_BUF_SIZE] = {0};
5741 char buf[32] = {0};
5742 if (!output)
5743 return RETURN_ERR;
5744
5745 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5746 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5747
5748 strcpy(output,"None");//Copying "None" to output string for default case
5749 if((strcmp(buf, "3")==0))
5750 snprintf(output, 32, "WPA-WPA2-Personal");
5751 else if((strcmp(buf, "2")==0))
5752 snprintf(output, 32, "WPA2-Personal");
5753 else if((strcmp(buf, "1")==0))
5754 snprintf(output, 32, "WPA-Personal");
5755 //TODO: need to handle enterprise authmode
5756
5757 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5758 return RETURN_OK;
5759#if 0
5760 //TODO: need to revisit below implementation
5761 char securityType[32], authMode[32];
5762 int enterpriseMode=0;
5763
5764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5765 if(!output)
5766 return RETURN_ERR;
5767
5768 wifi_getApBeaconType(apIndex, securityType);
5769 strcpy(output,"None");//By default, copying "None" to output string
5770 if (strncmp(securityType,"None", strlen("None")) == 0)
5771 return RETURN_OK;
5772
5773 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5774 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5775
5776 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5777 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5778 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5779 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5780 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5781 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5782 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5783
5784 return RETURN_OK;
5785#endif
5786}
5787
5788INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
5789{
5790 char securityType[32];
5791 char authMode[32];
5792
5793 //store settings and wait for wifi up to apply
5794 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5795 if(!encMode)
5796 return RETURN_ERR;
5797
5798 printf("%s: apIndex %d, encMode %s\n",__func__, apIndex, encMode);
5799 if (strcmp(encMode, "None")==0)
5800 {
5801 strcpy(securityType,"None");
5802 strcpy(authMode,"None");
5803 }
5804 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
5805 {
5806 strcpy(securityType,"WPAand11i");
5807 strcpy(authMode,"PSKAuthentication");
5808 }
5809 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
5810 {
5811 strcpy(securityType,"WPAand11i");
5812 strcpy(authMode,"EAPAuthentication");
5813 }
5814 else if (strcmp(encMode, "WPA-Personal")==0)
5815 {
5816 strcpy(securityType,"WPA");
5817 strcpy(authMode,"PSKAuthentication");
5818 }
5819 else if (strcmp(encMode, "WPA-Enterprise")==0)
5820 {
5821 strcpy(securityType,"WPA");
5822 strcpy(authMode,"EAPAuthentication");
5823 }
5824 else if (strcmp(encMode, "WPA2-Personal")==0)
5825 {
5826 strcpy(securityType,"11i");
5827 strcpy(authMode,"PSKAuthentication");
5828 }
5829 else if (strcmp(encMode, "WPA2-Enterprise")==0)
5830 {
5831 strcpy(securityType,"11i");
5832 strcpy(authMode,"EAPAuthentication");
5833 }
5834 else
5835 {
5836 strcpy(securityType,"None");
5837 strcpy(authMode,"None");
5838 }
5839 wifi_setApBeaconType(apIndex, securityType);
5840 wifi_setApBasicAuthenticationMode(apIndex, authMode);
5841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5842
5843 return RETURN_OK;
5844}
5845
5846
5847//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
5848// output_string must be pre-allocated as 64 character string by caller
5849// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5850INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
5851{
5852 char buf[16];
5853 char config_file[MAX_BUF_SIZE] = {0};
5854
5855 if(output_string==NULL)
5856 return RETURN_ERR;
5857
5858 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5859 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5860
5861 if(strcmp(buf,"0")==0)
5862 {
5863 printf("wpa_mode is %s ......... \n",buf);
5864 return RETURN_ERR;
5865 }
5866
5867 wifi_dbg_printf("\nFunc=%s\n",__func__);
5868 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5869 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5870 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5871
5872 return RETURN_OK;
5873}
5874
5875// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
5876// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
5877INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
5878{
5879 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5880 struct params params={'\0'};
5881 int ret;
5882 char config_file[MAX_BUF_SIZE] = {0};
5883
5884 if(NULL == preSharedKey)
5885 return RETURN_ERR;
5886
5887 params.name = "wpa_passphrase";
5888
5889 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
5890 {
5891 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5892 return RETURN_ERR;
5893 }
5894 params.value = preSharedKey;
5895 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5896 ret = wifi_hostapdWrite(config_file, &params, 1);
5897 if(!ret)
5898 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5899 return ret;
5900 //TODO: call hostapd_cli for dynamic_config_control
5901}
5902
5903//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
5904// outputs the passphrase, maximum 63 characters
5905INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
5906{
5907 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
5908
5909 wifi_dbg_printf("\nFunc=%s\n",__func__);
5910 if (NULL == output_string)
5911 return RETURN_ERR;
5912
5913 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5914 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5915 if(strcmp(buf,"0")==0)
5916 {
5917 printf("wpa_mode is %s ......... \n",buf);
5918 return RETURN_ERR;
5919 }
5920
5921 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
5922 wifi_dbg_printf("\noutput_string=%s\n",output_string);
5923
5924 return RETURN_OK;
5925}
5926
5927// sets the passphrase enviornment variable, max 63 characters
5928INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
5929{
5930 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
5931 struct params params={'\0'};
5932 char config_file[MAX_BUF_SIZE] = {0};
5933 int ret;
5934
5935 if(NULL == passPhrase)
5936 return RETURN_ERR;
5937
5938 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
5939 {
5940 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
5941 return RETURN_ERR;
5942 }
5943 params.name = "wpa_passphrase";
5944 params.value = passPhrase;
5945 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5946 ret=wifi_hostapdWrite(config_file,&params,1);
5947 if(!ret)
5948 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5949
5950 return ret;
5951}
5952
5953//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.
5954INT wifi_setApSecurityReset(INT apIndex)
5955{
developer8d583982022-09-20 11:28:22 +08005956 char original_config_file[64] = {0};
5957 char current_config_file[64] = {0};
5958 char buf[64] = {0};
5959 char cmd[64] = {0};
5960 char wpa[4] = {0};
5961 char wpa_psk[64] = {0};
5962 char wpa_passphrase[64] = {0};
5963 char wpa_psk_file[128] = {0};
5964 char wpa_key_mgmt[64] = {0};
5965 char wpa_pairwise[32] = {0};
5966 wifi_band band;
5967 struct params list[6];
5968
5969 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5970
5971 band = wifi_index_to_band(apIndex);
5972 if (band == band_2_4)
5973 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5974 else if (band = band_5)
5975 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5976 else if (band = band_6)
5977 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5978 else
5979 return RETURN_ERR;
5980
5981 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
5982 list[0].name = "wpa";
5983 list[0].value = wpa;
5984
5985 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
5986 list[1].name = "wpa_psk";
5987 list[1].value = wpa_psk;
5988
5989 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
5990 list[2].name = "wpa_passphrase";
5991 list[2].value = wpa_passphrase;
5992
5993 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
5994
5995 if (strlen(wpa_psk_file) == 0)
5996 strcpy(wpa_psk_file, PSK_FILE);
5997
5998 if (access(wpa_psk_file, F_OK) != 0) {
5999 sprintf(cmd, "touch %s", wpa_psk_file);
6000 _syscmd(cmd, buf, sizeof(buf));
6001 }
6002 list[3].name = "wpa_psk_file";
6003 list[3].value = wpa_psk_file;
6004
6005 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6006 list[4].name = "wpa_key_mgmt";
6007 list[4].value = wpa_key_mgmt;
6008
6009 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6010 list[5].name = "wpa_pairwise";
6011 list[5].value = wpa_pairwise;
6012
6013 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6014 wifi_hostapdWrite(current_config_file, list, 6);
6015
6016 wifi_setApEnable(apIndex, FALSE);
6017 wifi_setApEnable(apIndex, TRUE);
6018
6019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6020 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006021}
6022
6023//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).
6024INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6025{
developer8f2ddd52022-09-13 15:39:24 +08006026 char config_file[64] = {0};
6027 char buf[64] = {0};
6028 char cmd[256] = {0};
6029
6030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6031
developer06a01d92022-09-07 16:32:39 +08006032 if(!IP_output || !Port_output || !RadiusSecret_output)
6033 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006034
developer8f2ddd52022-09-13 15:39:24 +08006035 // Read the first matched config
6036 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6037 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6038 _syscmd(cmd, buf, sizeof(buf));
6039 strncpy(IP_output, buf, 64);
6040
6041 memset(buf, 0, sizeof(buf));
6042 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6043 _syscmd(cmd, buf, sizeof(buf));
6044 *Port_output = atoi(buf);
6045
6046 memset(buf, 0, sizeof(buf));
6047 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6048 _syscmd(cmd, buf, sizeof(buf));
6049 strncpy(RadiusSecret_output, buf, 64);
6050
6051 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006052 return RETURN_OK;
6053}
6054
6055INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6056{
developer8f2ddd52022-09-13 15:39:24 +08006057 char config_file[64] = {0};
6058 char port_str[8] = {0};
6059 char cmd[256] = {0};
6060 char buf[128] = {0};
6061
6062 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6063
6064 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6065
6066 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6067 _syscmd(cmd, buf, sizeof(buf));
6068 memset(cmd, 0, sizeof(cmd));
6069
6070 snprintf(port_str, sizeof(port_str), "%d", port);
6071 if (strlen(buf) == 0)
6072 // Append
6073 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6074 "auth_server_addr=%s\\n"
6075 "auth_server_port=%s\\n"
6076 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6077 else {
6078 // Delete the three lines setting after the "# radius 1" comment
6079 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6080 _syscmd(cmd, buf, sizeof(buf));
6081 memset(cmd, 0, sizeof(cmd));
6082 // Use "# radius 1" comment to find the location to insert the radius setting
6083 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6084 "# radius 1\\n"
6085 "auth_server_addr=%s\\n"
6086 "auth_server_port=%s\\n"
6087 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6088 }
6089 if(_syscmd(cmd, buf, sizeof(buf))) {
6090 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6091 return RETURN_ERR;
6092 }
6093
6094 wifi_reloadAp(apIndex);
6095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6096 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006097}
6098
6099INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6100{
developer8f2ddd52022-09-13 15:39:24 +08006101 char config_file[64] = {0};
6102 char buf[64] = {0};
6103 char cmd[256] = {0};
6104
6105 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6106
developer06a01d92022-09-07 16:32:39 +08006107 if(!IP_output || !Port_output || !RadiusSecret_output)
6108 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006109
6110 // Read the second matched config
6111 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6112 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6113 _syscmd(cmd, buf, sizeof(buf));
6114 strncpy(IP_output, buf, 64);
6115
6116 memset(buf, 0, sizeof(buf));
6117 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6118 _syscmd(cmd, buf, sizeof(buf));
6119 *Port_output = atoi(buf);
6120
6121 memset(buf, 0, sizeof(buf));
6122 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6123 _syscmd(cmd, buf, sizeof(buf));
6124 strncpy(RadiusSecret_output, buf, 64);
6125
6126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006127 return RETURN_OK;
6128}
6129
6130INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6131{
developer8f2ddd52022-09-13 15:39:24 +08006132 char config_file[64] = {0};
6133 char port_str[8] = {0};
6134 char cmd[256] = {0};
6135 char buf[128] = {0};
6136
6137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6138
6139 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6140
6141 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6142 _syscmd(cmd, buf, sizeof(buf));
6143 memset(cmd, 0, sizeof(cmd));
6144
6145 snprintf(port_str, sizeof(port_str), "%d", port);
6146 if (strlen(buf) == 0)
6147 // Append
6148 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6149 "auth_server_addr=%s\\n"
6150 "auth_server_port=%s\\n"
6151 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6152 else {
6153 // Delete the three lines setting after the "# radius 2" comment
6154 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6155 _syscmd(cmd, buf, sizeof(buf));
6156 memset(cmd, 0, sizeof(cmd));
6157 // Use "# radius 2" comment to find the location to insert the radius setting
6158 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6159 "# radius 2\\n"
6160 "auth_server_addr=%s\\n"
6161 "auth_server_port=%s\\n"
6162 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6163 }
6164 if(_syscmd(cmd, buf, sizeof(buf))) {
6165 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6166 return RETURN_ERR;
6167 }
6168
6169 wifi_reloadAp(apIndex);
6170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6171 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006172}
6173
6174//RadiusSettings
6175INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6176{
6177 if(!output)
6178 return RETURN_ERR;
6179
6180 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6181 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6182 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6183 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6184 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6185 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.
6186 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6187 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6188 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6189 //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.
6190
6191 return RETURN_OK;
6192}
6193
6194INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6195{
6196 //store the paramters, and apply instantly
6197 return RETURN_ERR;
6198}
6199
6200//Device.WiFi.AccessPoint.{i}.WPS.Enable
6201//Enables or disables WPS functionality for this access point.
6202// outputs the WPS enable state of this ap in output_bool
6203INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6204{
6205 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6206 if(!output_bool || !(apIndex==0 || apIndex==1))
6207 return RETURN_ERR;
6208 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6209 _syscmd(cmd, buf, sizeof(buf));
6210 if(strstr(buf, "configured"))
6211 *output_bool=TRUE;
6212 else
6213 *output_bool=FALSE;
6214
6215 return RETURN_OK;
6216}
6217
6218//Device.WiFi.AccessPoint.{i}.WPS.Enable
6219// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6220INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6221{
6222 char config_file[MAX_BUF_SIZE] = {0};
6223 struct params params;
6224
6225 if(!(apIndex==0 || apIndex==1))
6226 return RETURN_ERR;
6227 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6228 //store the paramters, and wait for wifi up to apply
6229 params.name = "wps_state";
6230 params.value = enable ? "2":"0";
6231
6232 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6233 wifi_hostapdWrite(config_file, &params, 1);
6234 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6235 wifi_reloadAp(apIndex);
6236
6237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6238 return RETURN_OK;
6239}
6240
6241//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
6242INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6243{
6244 if(!output)
6245 return RETURN_ERR;
6246 snprintf(output, 128, "PushButton,PIN");
6247 return RETURN_OK;
6248}
6249
6250//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6251//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.
6252// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6253INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6254{
6255 if(!output)
6256 return RETURN_ERR;
6257 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6258
6259 return RETURN_OK;
6260}
6261
6262//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6263// 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
6264INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6265{
6266 //apply instantly. No setting need to be stored.
6267 char methods[MAX_BUF_SIZE], *token, *next_token;
6268 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6269 struct params params;
6270
6271 if(!methodString || !(apIndex==0 || apIndex==1))
6272 return RETURN_ERR;
6273 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6274 //store the paramters, and wait for wifi up to apply
6275
6276 snprintf(methods, sizeof(methods), "%s", methodString);
6277 for(token=methods; *token; token=next_token)
6278 {
6279 strtok_r(token, ",", &next_token);
6280 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6281 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6282 else if(*token=='E')
6283 {
6284 if(!strcmp(methods, "Ethernet"))
6285 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6286 else if(!strcmp(methods, "ExternalNFCToken"))
6287 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6288 else
6289 printf("%s: Unknown WpsConfigMethod\n", __func__);
6290 }
6291 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6292 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6293 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6294 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6295 else if(*token=='P' )
6296 {
6297 if(!strcmp(token, "PushButton"))
6298 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6299 else if(!strcmp(token, "PIN"))
6300 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6301 else
6302 printf("%s: Unknown WpsConfigMethod\n", __func__);
6303 }
6304 else
6305 printf("%s: Unknown WpsConfigMethod\n", __func__);
6306 }
6307 params.name = "config_methods";
6308 params.value = config_methods;
6309 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6310 wifi_hostapdWrite(config_file, &params, 1);
6311 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6313
6314 return RETURN_OK;
6315}
6316
6317// outputs the pin value, ulong_pin must be allocated by the caller
6318INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6319{
6320 char buf[MAX_BUF_SIZE] = {0};
6321 char cmd[MAX_CMD_SIZE] = {0};
6322
6323 if(!output_ulong || !(apIndex==0 || apIndex==1))
6324 return RETURN_ERR;
6325 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6326 _syscmd(cmd, buf, sizeof(buf));
6327 if(strlen(buf) > 0)
6328 *output_ulong=strtoul(buf, NULL, 10);
6329
6330 return RETURN_OK;
6331}
6332
6333// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6334INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6335{
6336 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6337 char ap_pin[16] = {0};
6338 char buf[MAX_BUF_SIZE] = {0};
6339 char config_file[MAX_BUF_SIZE] = {0};
6340 ULONG prev_pin = 0;
6341 struct params params;
6342
6343 if(!(apIndex==0 || apIndex==1))
6344 return RETURN_ERR;
6345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6346 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6347 params.name = "ap_pin";
6348 params.value = ap_pin;
6349 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6350 wifi_hostapdWrite(config_file, &params, 1);
6351 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6352 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6353
6354 return RETURN_OK;
6355}
6356
6357// Output string is either Not configured or Configured, max 32 characters
6358INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6359{
6360 char cmd[MAX_CMD_SIZE];
6361 char buf[MAX_BUF_SIZE]={0};
6362
6363 if(!output_string || !(apIndex==0 || apIndex==1))
6364 return RETURN_ERR;
6365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6366 snprintf(output_string, 32, "Not configured");
6367 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6368 _syscmd(cmd, buf, sizeof(buf));
6369
developer348e3d92022-09-13 14:48:41 +08006370 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006371 snprintf(output_string, 32, "Configured");
6372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6373
6374 return RETURN_OK;
6375}
6376
6377// sets the WPS pin for this AP
6378INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6379{
6380 char cmd[MAX_CMD_SIZE];
6381 char buf[MAX_BUF_SIZE]={0};
6382 BOOL enable;
6383
6384 if(!(apIndex==0 || apIndex==1))
6385 return RETURN_ERR;
6386 wifi_getApEnable(apIndex, &enable);
6387 if (!enable)
6388 return RETURN_ERR;
6389 wifi_getApWpsEnable(apIndex, &enable);
6390 if (!enable)
6391 return RETURN_ERR;
6392
6393 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6394 _syscmd(cmd, buf, sizeof(buf));
6395 if((strstr(buf, "OK"))!=NULL)
6396 return RETURN_OK;
6397
6398 return RETURN_ERR;
6399}
6400
6401// This function is called when the WPS push button has been pressed for this AP
6402INT wifi_setApWpsButtonPush(INT apIndex)
6403{
6404 char cmd[MAX_CMD_SIZE];
6405 char buf[MAX_BUF_SIZE]={0};
6406 BOOL enable=FALSE;
6407
6408 if(!(apIndex==0 || apIndex==1))
6409 return RETURN_ERR;
6410 wifi_getApEnable(apIndex, &enable);
6411 if (!enable)
6412 return RETURN_ERR;
6413
6414 wifi_getApWpsEnable(apIndex, &enable);
6415 if (!enable)
6416 return RETURN_ERR;
6417
6418 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6419 _syscmd(cmd, buf, sizeof(buf));
6420
6421 if((strstr(buf, "OK"))!=NULL)
6422 return RETURN_OK;
6423 return RETURN_ERR;
6424}
6425
6426// cancels WPS mode for this AP
6427INT wifi_cancelApWPS(INT apIndex)
6428{
6429 char cmd[MAX_CMD_SIZE];
6430 char buf[MAX_BUF_SIZE]={0};
6431
6432 if(!(apIndex==0 || apIndex==1))
6433 return RETURN_ERR;
6434 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6435 _syscmd(cmd,buf, sizeof(buf));
6436
6437 if((strstr(buf, "OK"))!=NULL)
6438 return RETURN_OK;
6439 return RETURN_ERR;
6440}
6441
6442//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6443//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6444INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6445{
6446 FILE *f;
6447 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6448 char cmd[256], buf[2048];
6449 char *param , *value, *line=NULL;
6450 size_t len = 0;
6451 ssize_t nread;
6452 wifi_associated_dev_t *dev=NULL;
6453
6454 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6455 *associated_dev_array = NULL;
6456 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6457 _syscmd(cmd,buf,sizeof(buf));
6458 *output_array_size = atoi(buf);
6459
6460 if (*output_array_size <= 0)
6461 return RETURN_OK;
6462
6463 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6464 *associated_dev_array = dev;
6465 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6466 _syscmd(cmd,buf,sizeof(buf));
6467 f = fopen("/tmp/connected_devices.txt", "r");
6468 if (f==NULL)
6469 {
6470 *output_array_size=0;
6471 return RETURN_ERR;
6472 }
6473 while ((nread = getline(&line, &len, f)) != -1)
6474 {
6475 param = strtok(line,"=");
6476 value = strtok(NULL,"=");
6477
6478 if( strcmp("flags",param) == 0 )
6479 {
6480 value[strlen(value)-1]='\0';
6481 if(strstr (value,"AUTHORIZED") != NULL )
6482 {
6483 dev[auth_temp].cli_AuthenticationState = 1;
6484 dev[auth_temp].cli_Active = 1;
6485 auth_temp++;
6486 read_flag=1;
6487 }
6488 }
6489 if(read_flag==1)
6490 {
6491 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6492 {
6493 value[strlen(value)-1]='\0';
6494 sscanf(value, "%x:%x:%x:%x:%x:%x",
6495 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6496 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6497 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6498 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6499 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6500 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6501 mac_temp++;
6502 read_flag=0;
6503 }
6504 }
6505 }
6506 *output_array_size = auth_temp;
6507 auth_temp=0;
6508 mac_temp=0;
6509 free(line);
6510 fclose(f);
6511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6512 return RETURN_OK;
6513}
6514
6515#define MACADDRESS_SIZE 6
6516
6517INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6518{
6519 FILE *fp = NULL;
6520 char str[MAX_BUF_SIZE] = {0};
6521 int wificlientindex = 0 ;
6522 int count = 0;
6523 int signalstrength = 0;
6524 int arr[MACADDRESS_SIZE] = {0};
6525 unsigned char mac[MACADDRESS_SIZE] = {0};
6526 UINT wifi_count = 0;
6527 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6528 char pipeCmd[MAX_CMD_SIZE] = {0};
6529
6530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6531 *output_array_size = 0;
6532 *associated_dev_array = NULL;
6533
6534 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6535 fp = popen(pipeCmd, "r");
6536 if (fp == NULL)
6537 {
6538 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6539 return RETURN_ERR;
6540 }
6541
6542 /* Read the output a line at a time - output it. */
6543 fgets(str, sizeof(str)-1, fp);
6544 wifi_count = (unsigned int) atoi ( str );
6545 *output_array_size = wifi_count;
6546 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6547 pclose(fp);
6548
6549 if(wifi_count == 0)
6550 {
6551 return RETURN_OK;
6552 }
6553 else
6554 {
6555 wifi_associated_dev3_t* temp = NULL;
6556 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6557 if(temp == NULL)
6558 {
6559 printf("Error Statement. Insufficient memory \n");
6560 return RETURN_ERR;
6561 }
6562
6563 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6564 system(pipeCmd);
6565 memset(pipeCmd,0,sizeof(pipeCmd));
6566 if(apIndex == 0)
6567 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6568 else if(apIndex == 1)
6569 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6570 system(pipeCmd);
6571
6572 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6573 if(fp == NULL)
6574 {
6575 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6576 return RETURN_ERR;
6577 }
6578 fclose(fp);
6579
6580 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6581 fp = popen(pipeCmd, "r");
6582 if(fp)
6583 {
6584 for(count =0 ; count < wifi_count; count++)
6585 {
6586 fgets(str, MAX_BUF_SIZE, fp);
6587 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6588 {
6589 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6590 {
6591 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6592
6593 }
6594 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6595 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]);
6596 }
6597 temp[count].cli_AuthenticationState = 1; //TODO
6598 temp[count].cli_Active = 1; //TODO
6599 }
6600 pclose(fp);
6601 }
6602
6603 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6604 fp = popen(pipeCmd, "r");
6605 if(fp)
6606 {
6607 pclose(fp);
6608 }
6609 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6610 if(fp)
6611 {
6612 for(count =0 ; count < wifi_count ;count++)
6613 {
6614 fgets(str, MAX_BUF_SIZE, fp);
6615 signalstrength = atoi(str);
6616 temp[count].cli_SignalStrength = signalstrength;
6617 temp[count].cli_RSSI = signalstrength;
6618 temp[count].cli_SNR = signalstrength + 95;
6619 }
6620 pclose(fp);
6621 }
6622
6623
6624 if((apIndex == 0) || (apIndex == 4))
6625 {
6626 for(count =0 ; count < wifi_count ;count++)
6627 {
6628 strcpy(temp[count].cli_OperatingStandard,"g");
6629 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6630 }
6631
6632 //BytesSent
6633 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6634 fp = popen(pipeCmd, "r");
6635 if(fp)
6636 {
6637 pclose(fp);
6638 }
6639 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6640 if(fp)
6641 {
6642 for (count = 0; count < wifi_count; count++)
6643 {
6644 fgets(str, MAX_BUF_SIZE, fp);
6645 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6646 }
6647 pclose(fp);
6648 }
6649
6650 //BytesReceived
6651 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6652 fp = popen(pipeCmd, "r");
6653 if (fp)
6654 {
6655 pclose(fp);
6656 }
6657 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6658 if (fp)
6659 {
6660 for (count = 0; count < wifi_count; count++)
6661 {
6662 fgets(str, MAX_BUF_SIZE, fp);
6663 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6664 }
6665 pclose(fp);
6666 }
6667
6668 //PacketsSent
6669 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6670 fp = popen(pipeCmd, "r");
6671 if (fp)
6672 {
6673 pclose(fp);
6674 }
6675
6676 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6677 if (fp)
6678 {
6679 for (count = 0; count < wifi_count; count++)
6680 {
6681 fgets(str, MAX_BUF_SIZE, fp);
6682 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6683 }
6684 pclose(fp);
6685 }
6686
6687 //PacketsReceived
6688 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6689 fp = popen(pipeCmd, "r");
6690 if (fp)
6691 {
6692 pclose(fp);
6693 }
6694 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6695 if (fp)
6696 {
6697 for (count = 0; count < wifi_count; count++)
6698 {
6699 fgets(str, MAX_BUF_SIZE, fp);
6700 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6701 }
6702 pclose(fp);
6703 }
6704
6705 //ErrorsSent
6706 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6707 fp = popen(pipeCmd, "r");
6708 if (fp)
6709 {
6710 pclose(fp);
6711 }
6712 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6713 if (fp)
6714 {
6715 for (count = 0; count < wifi_count; count++)
6716 {
6717 fgets(str, MAX_BUF_SIZE, fp);
6718 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6719 }
6720 pclose(fp);
6721 }
6722
6723 //ErrorsSent
6724 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6725 fp = popen(pipeCmd, "r");
6726 if (fp)
6727 {
6728 pclose(fp);
6729 }
6730 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6731 if (fp)
6732 {
6733 for (count = 0; count < wifi_count; count++)
6734 {
6735 fgets(str, MAX_BUF_SIZE, fp);
6736 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6737 }
6738 pclose(fp);
6739 }
6740
6741 //LastDataDownlinkRate
6742 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6743 fp = popen(pipeCmd, "r");
6744 if (fp)
6745 {
6746 pclose(fp);
6747 }
6748 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
6749 if (fp)
6750 {
6751 for (count = 0; count < wifi_count; count++)
6752 {
6753 fgets(str, MAX_BUF_SIZE, fp);
6754 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
6755 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
6756 }
6757 pclose(fp);
6758 }
6759
6760 //LastDataUplinkRate
6761 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
6762 fp = popen(pipeCmd, "r");
6763 if (fp)
6764 {
6765 pclose(fp);
6766 }
6767 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
6768 if (fp)
6769 {
6770 for (count = 0; count < wifi_count; count++)
6771 {
6772 fgets(str, MAX_BUF_SIZE, fp);
6773 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
6774 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
6775 }
6776 pclose(fp);
6777 }
6778
6779 }
6780 else if ((apIndex == 1) || (apIndex == 5))
6781 {
6782 for (count = 0; count < wifi_count; count++)
6783 {
6784 strcpy(temp[count].cli_OperatingStandard, "a");
6785 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
6786 temp[count].cli_BytesSent = 0;
6787 temp[count].cli_BytesReceived = 0;
6788 temp[count].cli_LastDataUplinkRate = 0;
6789 temp[count].cli_LastDataDownlinkRate = 0;
6790 temp[count].cli_PacketsSent = 0;
6791 temp[count].cli_PacketsReceived = 0;
6792 temp[count].cli_ErrorsSent = 0;
6793 }
6794 }
6795
6796 for (count = 0; count < wifi_count; count++)
6797 {
6798 temp[count].cli_Retransmissions = 0;
6799 temp[count].cli_DataFramesSentAck = 0;
6800 temp[count].cli_DataFramesSentNoAck = 0;
6801 temp[count].cli_MinRSSI = 0;
6802 temp[count].cli_MaxRSSI = 0;
6803 strncpy(temp[count].cli_InterferenceSources, "", 64);
6804 memset(temp[count].cli_IPAddress, 0, 64);
6805 temp[count].cli_RetransCount = 0;
6806 temp[count].cli_FailedRetransCount = 0;
6807 temp[count].cli_RetryCount = 0;
6808 temp[count].cli_MultipleRetryCount = 0;
6809 }
6810 *associated_dev_array = temp;
6811 }
6812 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6813 return RETURN_OK;
6814}
6815
6816int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
6817{
6818 FILE *fp = NULL;
6819 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
6820 char cmd[MAX_CMD_SIZE];
6821 int count = 0;
6822
6823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6824 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
6825 fp = popen(cmd,"r");
6826 if(fp == NULL)
6827 {
6828 printf("Failed to run command in Function %s\n",__FUNCTION__);
6829 return 0;
6830 }
6831 if(fgets(path, sizeof(path)-1, fp) != NULL)
6832 {
6833 for(count=0;path[count]!='\n';count++)
6834 status[count]=path[count];
6835 status[count]='\0';
6836 }
6837 strcpy(wifi_status,status);
6838 pclose(fp);
6839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6840 return RETURN_OK;
6841}
6842
6843/* #define HOSTAPD_STA_PARAM_ENTRIES 29
6844struct hostapd_sta_param {
6845 char key[50];
6846 char value[100];
6847}
6848
6849static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
6850 int i = 0;
6851
6852 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
6853 if (strncmp(params[i].key,key,50) == 0){
6854 return &params[i].value;
6855 }
6856 i++;
6857 }
6858 return NULL;
6859
6860} */
6861
6862static unsigned int count_occurences(const char *buf, const char *word)
6863{
6864 unsigned int n = 0;
6865 char *ptr = strstr(buf, word);
6866
6867 while (ptr++) {
6868 n++;
6869 ptr = strstr(ptr, word);
6870 }
6871
6872 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
6873 return n;
6874}
6875
6876static const char *get_line_from_str_buf(const char *buf, char *line)
6877{
6878 int i;
6879 int n = strlen(buf);
6880
6881 for (i = 0; i < n; i++) {
6882 line[i] = buf[i];
6883 if (buf[i] == '\n') {
6884 line[i] = '\0';
6885 return &buf[i + 1];
6886 }
6887 }
6888
6889 return NULL;
6890}
6891
6892INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6893{
6894 unsigned int assoc_cnt = 0;
6895 char interface_name[50] = {0};
6896 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
6897 char cmd[MAX_CMD_SIZE] = {'\0'};
6898 char line[256] = {'\0'};
6899 int i = 0;
6900 int ret = 0;
6901 const char *ptr = NULL;
6902 char *key = NULL;
6903 char *val = NULL;
6904 wifi_associated_dev3_t *temp = NULL;
6905 int rssi;
6906
6907 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6908
6909 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
6910 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
6911 return RETURN_ERR;
6912 }
6913
6914 // Example filtered output of 'iw dev' command:
6915 // Station 0a:69:72:10:d2:fa (on wifi0)
6916 // signal avg:-67 [-71, -71] dBm
6917 // Station 28:c2:1f:25:5f:99 (on wifi0)
6918 // signal avg:-67 [-71, -70] dBm
6919 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
6920 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
6921 return RETURN_ERR;
6922 }
6923
6924 ret = _syscmd(cmd, buf, sizeof(buf));
6925 if (ret == RETURN_ERR) {
6926 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
6927 return RETURN_ERR;
6928 }
6929
6930 *output_array_size = count_occurences(buf, "Station");
6931 if (*output_array_size == 0) return RETURN_OK;
6932
6933 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
6934 if (temp == NULL) {
6935 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
6936 return RETURN_ERR;
6937 }
6938 *associated_dev_array = temp;
6939
6940 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
6941 ptr = get_line_from_str_buf(buf, line);
6942 i = -1;
6943 while (ptr) {
6944 if (strstr(line, "Station")) {
6945 i++;
6946 key = strtok(line, " ");
6947 val = strtok(NULL, " ");
6948 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
6949 &temp[i].cli_MACAddress[0],
6950 &temp[i].cli_MACAddress[1],
6951 &temp[i].cli_MACAddress[2],
6952 &temp[i].cli_MACAddress[3],
6953 &temp[i].cli_MACAddress[4],
6954 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
6955 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
6956 free(*associated_dev_array);
6957 return RETURN_ERR;
6958 }
6959 }
6960 else if (i < 0) {
6961 ptr = get_line_from_str_buf(ptr, line);
6962 continue; // We didn't detect 'station' entry yet
6963 }
6964 else if (strstr(line, "signal avg")) {
6965 key = strtok(line, ":");
6966 val = strtok(NULL, " ");
6967 if (sscanf(val, "%d", &rssi) <= 0 ) {
6968 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
6969 free(*associated_dev_array);
6970 return RETURN_ERR;
6971 }
6972 temp[i].cli_RSSI = rssi;
6973 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
6974 }
6975 // Here other fields can be parsed if added to filter of 'iw dev' command
6976
6977 ptr = get_line_from_str_buf(ptr, line);
6978 };
6979
6980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6981
6982 return RETURN_OK;
6983}
6984
6985#if 0
6986//To-do
6987INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6988{
6989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6990
6991 //Using different approach to get required WiFi Parameters from system available commands
6992#if 0
6993 FILE *f;
6994 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6995 char cmd[256], buf[2048];
6996 char *param , *value, *line=NULL;
6997 size_t len = 0;
6998 ssize_t nread;
6999 wifi_associated_dev3_t *dev=NULL;
7000 *associated_dev_array = NULL;
7001 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7002 _syscmd(cmd,buf,sizeof(buf));
7003 *output_array_size = atoi(buf);
7004
7005 if (*output_array_size <= 0)
7006 return RETURN_OK;
7007
7008 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7009 *associated_dev_array = dev;
7010 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7011 _syscmd(cmd,buf,sizeof(buf));
7012 f = fopen("/tmp/connected_devices.txt", "r");
7013 if (f==NULL)
7014 {
7015 *output_array_size=0;
7016 return RETURN_ERR;
7017 }
7018 while ((nread = getline(&line, &len, f)) != -1)
7019 {
7020 param = strtok(line,"=");
7021 value = strtok(NULL,"=");
7022
7023 if( strcmp("flags",param) == 0 )
7024 {
7025 value[strlen(value)-1]='\0';
7026 if(strstr (value,"AUTHORIZED") != NULL )
7027 {
7028 dev[auth_temp].cli_AuthenticationState = 1;
7029 dev[auth_temp].cli_Active = 1;
7030 auth_temp++;
7031 read_flag=1;
7032 }
7033 }
7034 if(read_flag==1)
7035 {
7036 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7037 {
7038 value[strlen(value)-1]='\0';
7039 sscanf(value, "%x:%x:%x:%x:%x:%x",
7040 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7041 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7042 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7043 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7044 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7045 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7046
7047 }
7048 else if( strcmp("rx_packets",param) == 0 )
7049 {
7050 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7051 }
7052
7053 else if( strcmp("tx_packets",param) == 0 )
7054 {
7055 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7056 }
7057
7058 else if( strcmp("rx_bytes",param) == 0 )
7059 {
7060 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7061 }
7062
7063 else if( strcmp("tx_bytes",param) == 0 )
7064 {
7065 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7066 mac_temp++;
7067 read_flag=0;
7068 }
7069 }
7070 }
7071
7072 *output_array_size = auth_temp;
7073 auth_temp=0;
7074 mac_temp=0;
7075 free(line);
7076 fclose(f);
7077#endif
7078 char interface_name[MAX_BUF_SIZE] = {0};
7079 char wifi_status[MAX_BUF_SIZE] = {0};
7080 char hostapdconf[MAX_BUF_SIZE] = {0};
7081
7082 wifi_associated_dev3_t *dev_array = NULL;
7083 ULONG wifi_count = 0;
7084
7085 *associated_dev_array = NULL;
7086 *output_array_size = 0;
7087
7088 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7089 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7090 {
7091 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7092
7093 GetInterfaceName(interface_name, hostapdconf);
7094
7095 if(strlen(interface_name) > 1)
7096 {
7097 wifihal_interfacestatus(wifi_status,interface_name);
7098 if(strcmp(wifi_status,"RUNNING") == 0)
7099 {
7100 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7101
7102 *associated_dev_array = dev_array;
7103 *output_array_size = wifi_count;
7104 }
7105 else
7106 {
7107 *associated_dev_array = NULL;
7108 }
7109 }
7110 }
7111
7112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7113 return RETURN_OK;
7114}
7115#endif
7116
7117/* getIPAddress function */
7118/**
7119* @description Returning IpAddress of the Matched String
7120*
7121* @param
7122* @str Having MacAddress
7123* @ipaddr Having ipaddr
7124* @return The status of the operation
7125* @retval RETURN_OK if successful
7126* @retval RETURN_ERR if any error is detected
7127*
7128*/
7129
7130INT getIPAddress(char *str,char *ipaddr)
7131{
7132 FILE *fp = NULL;
7133 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7134 int LeaseTime = 0,ret = 0;
7135 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7136 {
7137 return RETURN_ERR;
7138 }
7139
7140 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7141 {
7142 /*
7143 Sample:sss
7144 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7145 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7146 */
7147 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7148 &(LeaseTime),
7149 phyAddr,
7150 ipAddr,
7151 hostName
7152 );
7153 if(ret != 4)
7154 continue;
7155 if(strcmp(str,phyAddr) == 0)
7156 strcpy(ipaddr,ipAddr);
7157 }
7158 return RETURN_OK;
7159}
7160
7161/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7162/**
7163* @description Returning Inactive wireless connected clients informations
7164*
7165* @param
7166* @filename Holding private_wifi 2g/5g content files
7167* @associated_dev_array Having inactiv wireless clients informations
7168* @output_array_size Returning Inactive wireless counts
7169* @return The status of the operation
7170* @retval RETURN_OK if successful
7171* @retval RETURN_ERR if any error is detected
7172*
7173*/
7174
7175INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7176{
7177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7178 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7179 FILE *fp = NULL;
7180 int arr[MACADDRESS_SIZE] = {0};
7181 unsigned char mac[MACADDRESS_SIZE] = {0};
7182 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7183 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7184 fp = popen(buf,"r");
7185 if(fp == NULL)
7186 return RETURN_ERR;
7187 else
7188 {
7189 fgets(path,sizeof(path),fp);
7190 maccount = atoi(path);
7191 }
7192 pclose(fp);
7193 *output_array_size = maccount;
7194 wifi_associated_dev3_t* temp = NULL;
7195 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7196 *associated_dev_array = temp;
7197 if(temp == NULL)
7198 {
7199 printf("Error Statement. Insufficient memory \n");
7200 return RETURN_ERR;
7201 }
7202 memset(buf,0,sizeof(buf));
7203 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7204 fp = popen(buf,"r");
7205 for(count = 0; count < maccount ; count++)
7206 {
7207 fgets(path,sizeof(path),fp);
7208 for(i = 0; path[i]!='\n';i++)
7209 str[i]=path[i];
7210 str[i]='\0';
7211 getIPAddress(str,ipaddr);
7212 memset(buf,0,sizeof(buf));
7213 if(strlen(ipaddr) > 0)
7214 {
7215 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7216 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7217 {
7218 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7219 {
7220 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7221 {
7222 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7223
7224 }
7225 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7226 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]);
7227 }
7228 temp[count].cli_AuthenticationState = 0; //TODO
7229 temp[count].cli_Active = 0; //TODO
7230 temp[count].cli_SignalStrength = 0;
7231 }
7232 else //Active wireless clients info
7233 {
7234 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7235 {
7236 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7237 {
7238 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7239
7240 }
7241 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7242 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]);
7243 }
7244 temp[count].cli_Active = 1;
7245 }
7246 }
7247 memset(ipaddr,0,sizeof(ipaddr));
7248 }
7249 pclose(fp);
7250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7251 return RETURN_OK;
7252}
7253//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7254//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7255//To get Band Steering Capability
7256INT wifi_getBandSteeringCapability(BOOL *support)
7257{
7258 *support = FALSE;
7259 return RETURN_OK;
7260}
7261
7262
7263//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7264//To get Band Steering enable status
7265INT wifi_getBandSteeringEnable(BOOL *enable)
7266{
7267 *enable = FALSE;
7268 return RETURN_OK;
7269}
7270
7271//To turn on/off Band steering
7272INT wifi_setBandSteeringEnable(BOOL enable)
7273{
7274 return RETURN_OK;
7275}
7276
7277//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7278//To get Band Steering AP group
7279INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7280{
7281 if (NULL == output_ApGroup)
7282 return RETURN_ERR;
7283
7284 strcpy(output_ApGroup, "1,2");
7285 return RETURN_OK;
7286}
7287
7288//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7289//to set and read the band steering BandUtilizationThreshold parameters
7290INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7291{
7292 return RETURN_ERR;
7293}
7294
7295INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7296{
7297 return RETURN_ERR;
7298}
7299
7300//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7301//to set and read the band steering RSSIThreshold parameters
7302INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7303{
7304 return RETURN_ERR;
7305}
7306
7307INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7308{
7309 return RETURN_ERR;
7310}
7311
7312
7313//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7314//to set and read the band steering physical modulation rate threshold parameters
7315INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7316{
7317 //If chip is not support, return -1
7318 return RETURN_ERR;
7319}
7320
7321INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7322{
7323 //If chip is not support, return -1
7324 return RETURN_ERR;
7325}
7326
7327//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7328//to set and read the inactivity time (in seconds) for steering under overload condition
7329INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7330{
7331 return RETURN_ERR;
7332}
7333
7334INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7335{
7336 return RETURN_ERR;
7337}
7338
7339//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7340//to set and read the inactivity time (in seconds) for steering under Idle condition
7341INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7342{
7343 return RETURN_ERR;
7344}
7345
7346INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7347{
7348 return RETURN_ERR;
7349}
7350
7351//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7352//pClientMAC[64]
7353//pSourceSSIDIndex[64]
7354//pDestSSIDIndex[64]
7355//pSteeringReason[256]
7356INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7357{
7358 //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
7359 *pSteeringTime=time(NULL);
7360 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7361 return RETURN_OK;
7362}
7363
7364INT wifi_ifConfigDown(INT apIndex)
7365{
7366 INT status = RETURN_OK;
7367 char cmd[64];
7368
7369 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7370 printf("%s: %s\n", __func__, cmd);
7371 system(cmd);
7372
7373 return status;
7374}
7375
7376INT wifi_ifConfigUp(INT apIndex)
7377{
7378 char cmd[128];
7379 char buf[1024];
7380
7381 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7382 _syscmd(cmd, buf, sizeof(buf));
7383 return 0;
7384}
7385
7386//>> Deprecated. Replace with wifi_applyRadioSettings
7387INT wifi_pushBridgeInfo(INT apIndex)
7388{
7389 char ip[32];
7390 char subnet[32];
7391 char bridge[32];
7392 int vlanId;
7393 char cmd[128];
7394 char buf[1024];
7395
7396 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7397 wifi_getApVlanID(apIndex,&vlanId);
7398
7399 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7400 _syscmd(cmd,buf, sizeof(buf));
7401
7402 return 0;
7403}
7404
7405INT wifi_pushChannel(INT radioIndex, UINT channel)
7406{
7407 char cmd[128];
7408 char buf[1024];
7409 int apIndex;
7410
7411 apIndex=(radioIndex==0)?0:1;
7412 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7413 _syscmd(cmd,buf, sizeof(buf));
7414
7415 return 0;
7416}
7417
7418INT wifi_pushChannelMode(INT radioIndex)
7419{
7420 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7421 return RETURN_ERR;
7422}
7423
7424INT wifi_pushDefaultValues(INT radioIndex)
7425{
7426 //Apply Comcast specified default radio settings instantly
7427 //AMPDU=1
7428 //AMPDUFrames=32
7429 //AMPDULim=50000
7430 //txqueuelen=1000
7431
7432 return RETURN_ERR;
7433}
7434
7435INT wifi_pushTxChainMask(INT radioIndex)
7436{
7437 //Apply default TxChainMask instantly
7438 return RETURN_ERR;
7439}
7440
7441INT wifi_pushRxChainMask(INT radioIndex)
7442{
7443 //Apply default RxChainMask instantly
7444 return RETURN_ERR;
7445}
7446
7447INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7448{
7449 INT status;
7450
7451 status = wifi_setSSIDName(apIndex,ssid);
7452 wifi_setApEnable(apIndex,FALSE);
7453 wifi_setApEnable(apIndex,TRUE);
7454
7455 return status;
7456}
7457
7458INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7459{
7460 //Apply default Ssid Advertisement instantly
7461 return RETURN_ERR;
7462}
7463
7464INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7465{
7466 INT status = RETURN_ERR;
7467 *output = 0;
7468 return RETURN_ERR;
7469}
7470
7471INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7472{
7473 return RETURN_OK;
7474}
7475
7476INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7477{
7478 return RETURN_OK;
7479}
7480
7481//To-do
7482INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7483{
developereb199ae2022-09-13 14:04:27 +08007484 char output[16]={'\0'};
7485 char config_file[MAX_BUF_SIZE] = {0};
7486
7487 if (!output_string)
7488 return RETURN_ERR;
7489
7490 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7491 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7492
7493 if (strlen(output) == 0)
7494 snprintf(output_string, 64, "Disabled");
7495 else if (strncmp(output, "0", 1) == 0)
7496 snprintf(output_string, 64, "Disabled");
7497 else if (strncmp(output, "1", 1) == 0)
7498 snprintf(output_string, 64, "Optional");
7499 else if (strncmp(output, "2", 1) == 0)
7500 snprintf(output_string, 64, "Required");
7501 else {
7502 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7503 return RETURN_ERR;
7504 }
7505
7506 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007507 return RETURN_OK;
7508}
7509INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7510{
developereb199ae2022-09-13 14:04:27 +08007511 char str[MAX_BUF_SIZE]={'\0'};
7512 char cmd[MAX_CMD_SIZE]={'\0'};
7513 struct params params;
7514 char config_file[MAX_BUF_SIZE] = {0};
7515
7516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7517 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7518 return RETURN_ERR;
7519
7520 params.name = "ieee80211w";
7521 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7522 params.value = "0";
7523 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7524 params.value = "1";
7525 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7526 params.value = "2";
7527 else{
7528 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7529 return RETURN_ERR;
7530 }
7531 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7532 wifi_hostapdWrite(config_file, &params, 1);
7533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007534 return RETURN_OK;
7535}
7536INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7537{
7538 char output[16]={'\0'};
7539 char config_file[MAX_BUF_SIZE] = {0};
7540
7541 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7542 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7543 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7544
7545 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7546 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7547
7548 return RETURN_OK;
7549}
7550
7551INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7552{
7553 return RETURN_OK;
7554}
7555
7556INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7557{
7558 return RETURN_OK;
7559}
7560
7561INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7562{
7563 return RETURN_OK;
7564}
7565
7566INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7567{
7568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7569 char config_file[MAX_BUF_SIZE] = {0};
7570
7571 if (NULL == output)
7572 return RETURN_ERR;
7573 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7574 wifi_hostapdRead(config_file,"hw_mode",output,64);
7575
7576 if(strcmp(output,"b")==0)
7577 sprintf(output, "%s", "1,2,5.5,11");
7578 else if (strcmp(output,"a")==0)
7579 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7580 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7581 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7582
7583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7584 return RETURN_OK;
7585}
7586
7587INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7588{
7589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7590 char *temp;
7591 char temp_output[128];
7592 char temp_TransmitRates[128];
7593 char config_file[MAX_BUF_SIZE] = {0};
7594
7595 if (NULL == output)
7596 return RETURN_ERR;
7597
7598 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7599 wifi_hostapdRead(config_file,"supported_rates",output,64);
7600
7601 strcpy(temp_TransmitRates,output);
7602 strcpy(temp_output,"");
7603 temp = strtok(temp_TransmitRates," ");
7604 while(temp!=NULL)
7605 {
7606 temp[strlen(temp)-1]=0;
7607 if((temp[0]=='5') && (temp[1]=='\0'))
7608 {
7609 temp="5.5";
7610 }
7611 strcat(temp_output,temp);
7612 temp = strtok(NULL," ");
7613 if(temp!=NULL)
7614 {
7615 strcat(temp_output,",");
7616 }
7617 }
7618 strcpy(output,temp_output);
7619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7620
7621 return RETURN_OK;
7622}
7623
7624INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7625{
7626 return RETURN_OK;
7627}
7628
7629
7630INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7631{
7632 int i=0;
7633 char *temp;
7634 char temp1[128];
7635 char temp_output[128];
7636 char temp_TransmitRates[128];
7637 struct params params={'\0'};
7638 char config_file[MAX_BUF_SIZE] = {0};
7639
7640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7641 if(NULL == output)
7642 return RETURN_ERR;
7643
7644 strcpy(temp_TransmitRates,output);
7645
7646 for(i=0;i<strlen(temp_TransmitRates);i++)
7647 {
7648 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7649 {
7650 continue;
7651 }
7652 else
7653 {
7654 return RETURN_ERR;
7655 }
7656 }
7657 strcpy(temp_output,"");
7658 temp = strtok(temp_TransmitRates," ");
7659 while(temp!=NULL)
7660 {
7661 strcpy(temp1,temp);
7662 if(wlanIndex==1)
7663 {
7664 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7665 {
7666 return RETURN_ERR;
7667 }
7668 }
7669
7670 if(strcmp(temp,"5.5")==0)
7671 {
7672 strcpy(temp1,"55");
7673 }
7674 else
7675 {
7676 strcat(temp1,"0");
7677 }
7678 strcat(temp_output,temp1);
7679 temp = strtok(NULL," ");
7680 if(temp!=NULL)
7681 {
7682 strcat(temp_output," ");
7683 }
7684 }
7685 strcpy(output,temp_output);
7686
7687
7688 params.name = "supported_rates";
7689 params.value = output;
7690
7691 wifi_dbg_printf("\n%s:",__func__);
7692 wifi_dbg_printf("params.value=%s\n",params.value);
7693 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7694 wifi_hostapdWrite(config_file,&params,1);
7695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7696
7697 return RETURN_OK;
7698}
7699
7700
7701static char *sncopy(char *dst, int dst_sz, const char *src)
7702{
7703 if (src && dst && dst_sz > 0) {
7704 strncpy(dst, src, dst_sz);
7705 dst[dst_sz - 1] = '\0';
7706 }
7707 return dst;
7708}
7709
7710static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7711{
7712 if (0 == strcmp(ht_mode, "HT40") ||
7713 0 == strcmp(ht_mode, "HT80") ||
7714 0 == strcmp(ht_mode, "HT160")) {
7715 switch (channel) {
7716 case 1 ... 7:
7717 case 36:
7718 case 44:
7719 case 52:
7720 case 60:
7721 case 100:
7722 case 108:
7723 case 116:
7724 case 124:
7725 case 132:
7726 case 140:
7727 case 149:
7728 case 157:
7729 return 1;
7730 case 8 ... 13:
7731 case 40:
7732 case 48:
7733 case 56:
7734 case 64:
7735 case 104:
7736 case 112:
7737 case 120:
7738 case 128:
7739 case 136:
7740 case 144:
7741 case 153:
7742 case 161:
7743 return -1;
7744 default:
7745 return -EINVAL;
7746 }
7747 }
7748
7749 return -EINVAL;
7750}
7751
7752static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
7753{
7754 if (NULL == hw_mode) return;
7755
7756 if (0 == strcmp(hw_mode, "ac"))
7757 sncopy(bw_mode, bw_mode_len, "ht vht");
7758
7759 if (0 == strcmp(hw_mode, "n"))
7760 sncopy(bw_mode, bw_mode_len, "ht");
7761
7762 return;
7763}
7764
7765static int util_chan_to_freq(int chan)
7766{
7767 if (chan == 14)
7768 return 2484;
7769 else if (chan < 14)
7770 return 2407 + chan * 5;
7771 else if (chan >= 182 && chan <= 196)
7772 return 4000 + chan * 5;
7773 else
7774 return 5000 + chan * 5;
7775 return 0;
7776}
7777
7778const int *util_unii_5g_chan2list(int chan, int width)
7779{
7780 static const int lists[] = {
7781 // <width>, <chan1>, <chan2>..., 0,
7782 20, 36, 0,
7783 20, 40, 0,
7784 20, 44, 0,
7785 20, 48, 0,
7786 20, 52, 0,
7787 20, 56, 0,
7788 20, 60, 0,
7789 20, 64, 0,
7790 20, 100, 0,
7791 20, 104, 0,
7792 20, 108, 0,
7793 20, 112, 0,
7794 20, 116, 0,
7795 20, 120, 0,
7796 20, 124, 0,
7797 20, 128, 0,
7798 20, 132, 0,
7799 20, 136, 0,
7800 20, 140, 0,
7801 20, 144, 0,
7802 20, 149, 0,
7803 20, 153, 0,
7804 20, 157, 0,
7805 20, 161, 0,
7806 20, 165, 0,
7807 40, 36, 40, 0,
7808 40, 44, 48, 0,
7809 40, 52, 56, 0,
7810 40, 60, 64, 0,
7811 40, 100, 104, 0,
7812 40, 108, 112, 0,
7813 40, 116, 120, 0,
7814 40, 124, 128, 0,
7815 40, 132, 136, 0,
7816 40, 140, 144, 0,
7817 40, 149, 153, 0,
7818 40, 157, 161, 0,
7819 80, 36, 40, 44, 48, 0,
7820 80, 52, 56, 60, 64, 0,
7821 80, 100, 104, 108, 112, 0,
7822 80, 116, 120, 124, 128, 0,
7823 80, 132, 136, 140, 144, 0,
7824 80, 149, 153, 157, 161, 0,
7825 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
7826 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
7827 -1 // final delimiter
7828 };
7829 const int *start;
7830 const int *p;
7831
7832 for (p = lists; *p != -1; p++) {
7833 if (*p == width) {
7834 for (start = ++p; *p != 0; p++) {
7835 if (*p == chan)
7836 return start;
7837 }
7838 }
7839 // move to the end of channel list of given width
7840 while (*p != 0) {
7841 p++;
7842 }
7843 }
7844
7845 return NULL;
7846}
7847
7848static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
7849{
7850 if (NULL == ht_mode)
7851 return 0;
7852
7853 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
7854 const int *chans = util_unii_5g_chan2list(channel, width);
7855 int sum = 0;
7856 int cnt = 0;
7857
7858 if (NULL == chans)
7859 return 0;
7860
7861 while (*chans) {
7862 sum += *chans;
7863 cnt++;
7864 chans++;
7865 }
7866 return sum / cnt;
7867}
7868
7869static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
7870{
7871 BOOL onlyG, onlyN, onlyA;
7872 CHAR tmp[64];
7873 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
7874 if (ret == RETURN_OK) {
7875 sncopy(hw_mode, hw_mode_size, tmp);
7876 }
7877 return ret;
7878}
7879
7880INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
7881{
7882 // Sample commands:
7883 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
7884 // hostapd_cli -i wifi0 chan_switch 30 2437
7885 char cmd[MAX_CMD_SIZE] = {0};
7886 char buf[MAX_BUF_SIZE] = {0};
7887 int freq = 0, ret = 0;
7888 char center_freq1_str[32] = ""; // center_freq1=%d
7889 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
7890 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
7891 char hw_mode[16] = ""; // n|ac
7892 char bw_mode[16] = ""; // ht|ht vht
7893 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
7894 int sec_chan_offset;
7895 int width;
7896
7897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7898
7899 freq = util_chan_to_freq(channel);
7900
7901 // Get radio mode HT20|HT40|HT80 etc.
7902 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
7903 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
7904 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
7905 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
7906 if (sec_chan_offset != -EINVAL)
7907 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
7908
7909
7910 // Provide bandwith if specified
7911 if (channel_width_MHz > 20) {
7912 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
7913 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
7914 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
7915
7916 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
7917 }
7918
7919 int center_chan = 0;
7920 if (channel_width_MHz > 20) {
7921 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
7922 if (center_chan > 0) {
7923 int center_freq1 = util_chan_to_freq(center_chan);
7924 if (center_freq1)
7925 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
7926 }
7927 }
7928
7929 {
7930 // Only the first AP, other are hanging on the same radio
7931 int apIndex = radioIndex;
7932 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
7933 AP_PREFIX, apIndex, csa_beacon_count, freq,
7934 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
7935 wifi_dbg_printf("execute: '%s'\n", cmd);
7936 ret = _syscmd(cmd, buf, sizeof(buf));
7937 }
7938
7939 wifi_setRadioChannel(radioIndex, channel);
7940
7941 char *ext_str = "None";
7942 if (sec_chan_offset == 1) ext_str = "Above";
7943 else if (sec_chan_offset == -1) ext_str = "Below";
7944 wifi_setRadioExtChannel(radioIndex, ext_str);
7945
7946 wifi_setRadioCenterChannel(radioIndex, center_chan);
7947
7948 char mhz_str[16];
7949 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
7950 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
7951
7952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7953
7954 return RETURN_OK;
7955}
7956
7957INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
7958{
7959 char cmd[1024] = {0};
7960 char buf[1024] = {0};
7961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7962 wifi_neighbor_ap2_t *scan_array = NULL;
7963 int scan_count=0;
7964 int i =0;
7965 int freq=0;
7966 size_t len=0;
7967 FILE *f = NULL;
7968 ssize_t read = 0;
7969 char *line =NULL;
7970 char radio_ifname[64];
7971 char secondary_chan[64];
7972 int vht_channel_width = 0;
7973
7974 if(wifi_getRadioIfName(radio_index,radio_ifname)!=RETURN_OK)
7975 return RETURN_ERR;
7976
7977 /* sched_start is not supported on open source ath9k ath10k firmware
7978 * Using active scan as a workaround */
7979 sprintf(cmd,"iw dev %s scan |grep '^BSS\\|SSID:\\|freq:\\|signal:\\|HT operation:\\|secondary channel offset:\\|* channel width:'", radio_ifname);
7980 if((f = popen(cmd, "r")) == NULL) {
7981 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
7982 return RETURN_ERR;
7983 }
7984 read = getline(&line, &len, f);
7985 while (read != -1) {
7986 if(strncmp(line,"BSS",3) == 0) {
7987 i = scan_count;
7988 scan_count++;
7989 scan_array = realloc(scan_array,sizeof(wifi_neighbor_ap2_t)*scan_count);
7990 memset(&(scan_array[i]),0, sizeof(wifi_neighbor_ap2_t));
7991 sscanf(line,"BSS %17s", scan_array[i].ap_BSSID);
7992
7993 read = getline(&line, &len, f);
7994 sscanf(line," freq: %d", &freq);
7995 scan_array[i].ap_Channel = ieee80211_frequency_to_channel(freq);
7996
7997 read = getline(&line, &len, f);
7998 sscanf(line," signal: %d", &(scan_array[i].ap_SignalStrength));
7999
8000 read = getline(&line, &len, f);
8001 sscanf(line," SSID: %s", scan_array[i].ap_SSID);
8002 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);
8003 read = getline(&line, &len, f);
8004 if(strncmp(line,"BSS",3)==0) {
8005 // No HT and no VHT => 20Mhz
8006 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11%s", radio_index%1 ? "A": "G");
8007 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8008 continue;
8009 }
8010 if(strncmp(line," HT operation:",14)!= 0) {
8011 wifi_dbg_printf("HT output parsing error (%s)\n", line);
8012 goto output_error;
8013 }
8014
8015 read = getline(&line, &len, f);
8016 sscanf(line," * secondary channel offset: %s", &secondary_chan);
8017
8018 if(!strcmp(secondary_chan, "no")) {
8019 //20Mhz
8020 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
8021 }
8022
8023 if(!strcmp(secondary_chan, "above")) {
8024 //40Mhz +
8025 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
8026 }
8027
8028 if(!strcmp(secondary_chan, "below")) {
8029 //40Mhz -
8030 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8031 }
8032
8033
8034 read = getline(&line, &len, f);
8035 if(strncmp(line," VHT operation:",15) !=0) {
8036 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8037 // No VHT
8038 continue;
8039 }
8040 read = getline(&line, &len, f);
8041 sscanf(line," * channel width: %d", &vht_channel_width);
8042 if(vht_channel_width == 1) {
8043 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT80");
8044 } else {
8045 snprintf(scan_array[i].ap_OperatingChannelBandwidth, sizeof(scan_array[i].ap_OperatingChannelBandwidth), "11AC_VHT40");
8046 }
8047
8048 }
8049 wifi_dbg_printf("%s: ap_OperatingChannelBandwidth = '%s'\n", __func__, scan_array[i].ap_OperatingChannelBandwidth);
8050 read = getline(&line, &len, f);
8051 }
8052 wifi_dbg_printf("%s:Counted BSS: %d\n",__func__, scan_count);
8053 *output_array_size = scan_count;
8054 *neighbor_ap_array = scan_array;
8055 free(line);
8056 pclose(f);
8057 return RETURN_OK;
8058
8059output_error:
8060 pclose(f);
8061 free(line);
8062 free(scan_array);
8063 return RETURN_ERR;
8064}
8065INT wifi_getApAssociatedDeviceStats(
8066 INT apIndex,
8067 mac_address_t *clientMacAddress,
8068 wifi_associated_dev_stats_t *associated_dev_stats,
8069 u64 *handle)
8070{
8071 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8072 char interface_name[50] = {0};
8073 char cmd[1024] = {0};
8074 char mac_str[18] = {0};
8075 char *key = NULL;
8076 char *val = NULL;
8077 FILE *f = NULL;
8078 char *line = NULL;
8079 size_t len = 0;
8080 ssize_t read = 0;
8081
8082 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8083 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8084 return RETURN_ERR;
8085 }
8086
8087 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8088 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8089 if((f = popen(cmd, "r")) == NULL) {
8090 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8091 return RETURN_ERR;
8092 }
8093
8094 while ((read = getline(&line, &len, f)) != -1) {
8095 key = strtok(line,":");
8096 val = strtok(NULL,":");
8097
8098 if(!strncmp(key,"rx bytes",8))
8099 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8100 if(!strncmp(key,"tx bytes",8))
8101 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8102 if(!strncmp(key,"rx packets",10))
8103 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8104 if(!strncmp(key,"tx packets",10))
8105 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8106 if(!strncmp(key,"tx retries",10))
8107 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8108 if(!strncmp(key,"tx failed",9))
8109 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8110 if(!strncmp(key,"rx drop misc",13))
8111 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8112 if(!strncmp(key,"rx bitrate",10)) {
8113 val = strtok(val, " ");
8114 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8115 }
8116 if(!strncmp(key,"tx bitrate",10)) {
8117 val = strtok(val, " ");
8118 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8119 }
8120 }
8121 free(line);
8122 pclose(f);
8123 return RETURN_OK;
8124}
8125
8126INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8127{
8128 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8129
8130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8131 if (NULL == output_string)
8132 return RETURN_ERR;
8133
8134 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8135 _syscmd(cmd, buf, sizeof(buf));
8136
8137 //size of SSID name restricted to value less than 32 bytes
8138 snprintf(output_string, 32, "%s", buf);
8139 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8140
8141 return RETURN_OK;
8142}
8143
8144INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8145{
8146 //char cmd[MAX_CMD_SIZE] = {0};
8147 char config_file[MAX_BUF_SIZE] = {0};
8148 char buf[32] = {0};
8149
8150 if (!output_filterMode)
8151 return RETURN_ERR;
8152
8153 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8154 //_syscmd(cmd, buf, sizeof(buf));
8155 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8156 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008157 if(strlen(buf) == 0) {
8158 *output_filterMode = 0;
8159 }
8160 else {
8161 int macaddr_acl_mode = strtol(buf, NULL, 10);
8162 if (macaddr_acl_mode == 1) {
8163 *output_filterMode = 1;
8164 } else if (macaddr_acl_mode == 0) {
8165 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8166 if (strlen(buf) == 0) {
8167 *output_filterMode = 0;
8168 } else {
8169 *output_filterMode = 2;
8170 }
8171 } else {
8172 return RETURN_ERR;
8173 }
8174 }
developer06a01d92022-09-07 16:32:39 +08008175
8176 return RETURN_OK;
8177}
8178
8179INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8180{
8181 FILE *fp = NULL;
8182 char str[MAX_BUF_SIZE] = {0};
8183 int wificlientindex = 0 ;
8184 int count = 0;
8185 int signalstrength = 0;
8186 int arr[MACADDRESS_SIZE] = {0};
8187 unsigned char mac[MACADDRESS_SIZE] = {0};
8188 UINT wifi_count = 0;
8189 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8190 char pipeCmd[MAX_CMD_SIZE] = {0};
8191
8192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8193 *output_array_size = 0;
8194 *associated_dev_array = NULL;
8195 char interface_name[50] = {0};
8196
8197 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8198 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8199 return RETURN_ERR;
8200 }
8201
8202 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8203 fp = popen(pipeCmd, "r");
8204 if (fp == NULL)
8205 {
8206 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8207 return RETURN_ERR;
8208 }
8209
8210 /* Read the output a line at a time - output it. */
8211 fgets(str, sizeof(str)-1, fp);
8212 wifi_count = (unsigned int) atoi ( str );
8213 *output_array_size = wifi_count;
8214 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8215 pclose(fp);
8216
8217 if(wifi_count == 0)
8218 {
8219 return RETURN_OK;
8220 }
8221 else
8222 {
8223 wifi_associated_dev2_t* temp = NULL;
8224 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8225 *associated_dev_array = temp;
8226 if(temp == NULL)
8227 {
8228 printf("Error Statement. Insufficient memory \n");
8229 return RETURN_ERR;
8230 }
8231
8232 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8233 system(pipeCmd);
8234
8235 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8236 if(fp == NULL)
8237 {
8238 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8239 return RETURN_ERR;
8240 }
8241 fclose(fp);
8242
8243 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8244 fp = popen(pipeCmd, "r");
8245 if(fp)
8246 {
8247 for(count =0 ; count < wifi_count; count++)
8248 {
8249 fgets(str, MAX_BUF_SIZE, fp);
8250 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8251 {
8252 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8253 {
8254 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8255
8256 }
8257 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8258 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]);
8259 }
8260 temp[count].cli_AuthenticationState = 1; //TODO
8261 temp[count].cli_Active = 1; //TODO
8262 }
8263 pclose(fp);
8264 }
8265
8266 //Updating RSSI per client
8267 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8268 fp = popen(pipeCmd, "r");
8269 if(fp)
8270 {
8271 pclose(fp);
8272 }
8273 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8274 if(fp)
8275 {
8276 for(count =0 ; count < wifi_count ;count++)
8277 {
8278 fgets(str, MAX_BUF_SIZE, fp);
8279 signalstrength = atoi(str);
8280 temp[count].cli_RSSI = signalstrength;
8281 }
8282 pclose(fp);
8283 }
8284
8285
8286 //LastDataDownlinkRate
8287 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8288 fp = popen(pipeCmd, "r");
8289 if (fp)
8290 {
8291 pclose(fp);
8292 }
8293 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8294 if (fp)
8295 {
8296 for (count = 0; count < wifi_count; count++)
8297 {
8298 fgets(str, MAX_BUF_SIZE, fp);
8299 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8300 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8301 }
8302 pclose(fp);
8303 }
8304
8305 //LastDataUplinkRate
8306 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8307 fp = popen(pipeCmd, "r");
8308 if (fp)
8309 {
8310 pclose(fp);
8311 }
8312 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8313 if (fp)
8314 {
8315 for (count = 0; count < wifi_count; count++)
8316 {
8317 fgets(str, MAX_BUF_SIZE, fp);
8318 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8319 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8320 }
8321 pclose(fp);
8322 }
8323 }
8324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8325 return RETURN_OK;
8326
8327}
8328
8329INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8330{
8331#if 0
8332 /*char buf[1024] = {0};
8333 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8334 _syscmd(cmd, buf, sizeof(buf));*/
8335
8336 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8337 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8338 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8339 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8340
8341 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.
8342 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].
8343 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].
8344 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].
8345 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8346 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8347
8348 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8349 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8350 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8351 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.
8352 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.
8353 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.
8354 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.
8355 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.
8356 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.
8357 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.
8358 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8359#endif
8360
8361 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008362 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008363 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008364 char pipeCmd[128] = {0};
8365 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008366 wifi_ssidTrafficStats2_t *out = output_struct;
8367
developerce736392022-09-13 15:24:34 +08008368 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008369 if (!output_struct)
8370 return RETURN_ERR;
8371
developerce736392022-09-13 15:24:34 +08008372 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8373 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8374 GetInterfaceName(interface_name, HConf_file);
8375 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008376
developer06a01d92022-09-07 16:32:39 +08008377 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008378 if (fp == NULL) {
8379 fprintf(stderr, "%s: popen failed\n", __func__);
8380 return RETURN_ERR;
8381 }
8382 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008383
developerce736392022-09-13 15:24:34 +08008384 if (strlen(str) == 0) // interface not exist
8385 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008386
developerce736392022-09-13 15:24:34 +08008387 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8388 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008389 pclose(fp);
8390
developerce736392022-09-13 15:24:34 +08008391 memset(str, 0, sizeof(str));
8392 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008393 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008394 if (fp == NULL) {
8395 fprintf(stderr, "%s: popen failed\n", __func__);
8396 return RETURN_ERR;
8397 }
8398 fgets(str, sizeof(str), fp);
8399
8400 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8401 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008402 pclose(fp);
developerce736392022-09-13 15:24:34 +08008403
8404 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8405 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8406
8407 // Not supported
8408 output_struct->ssid_RetransCount = 0;
8409 output_struct->ssid_FailedRetransCount = 0;
8410 output_struct->ssid_RetryCount = 0;
8411 output_struct->ssid_MultipleRetryCount = 0;
8412 output_struct->ssid_ACKFailureCount = 0;
8413 output_struct->ssid_AggregatedPacketCount = 0;
8414
developer06a01d92022-09-07 16:32:39 +08008415 return RETURN_OK;
8416}
8417
8418//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).
8419INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8420{
8421 char output_val[16]={'\0'};
8422 char config_file[MAX_BUF_SIZE] = {0};
8423
8424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8425 if (!output)
8426 return RETURN_ERR;
8427 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8428 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8429
8430 if( strcmp(output_val,"1") == 0 )
8431 *output = TRUE;
8432 else
8433 *output = FALSE;
8434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8435
8436 return RETURN_OK;
8437}
8438
8439INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8440{
8441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8442 char str[MAX_BUF_SIZE]={'\0'};
8443 char string[MAX_BUF_SIZE]={'\0'};
8444 char cmd[MAX_CMD_SIZE]={'\0'};
8445 char *ch;
8446 char config_file[MAX_BUF_SIZE] = {0};
8447 struct params params;
8448
8449 if(enable == TRUE)
8450 strcpy(string,"1");
8451 else
8452 strcpy(string,"0");
8453
8454 params.name = "ap_isolate";
8455 params.value = string;
8456
8457 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8458 wifi_hostapdWrite(config_file,&params,1);
8459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8460
8461 return RETURN_OK;
8462}
8463
8464INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8465{
8466 if (NULL == output_dBm)
8467 return RETURN_ERR;
8468
8469 *output_dBm = 0;
8470 return RETURN_OK;
8471}
8472
8473INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8474{
8475 return RETURN_OK;
8476}
8477INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8478{
8479 return RETURN_OK;
8480}
8481INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8482{
8483 return RETURN_OK;
8484}
8485INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8486{
8487 return RETURN_OK;
8488}
8489INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8490{
8491 return RETURN_OK;
8492}
8493INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8494{
8495 char config_file[MAX_BUF_SIZE] = {0};
8496 struct params list;
8497
8498 list.name = "bss_transition";
8499 list.value = activate?"1":"0";
8500 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8501 wifi_hostapdWrite(config_file, &list, 1);
8502
8503 return RETURN_OK;
8504}
8505wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8506
8507void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8508{
8509 return;
8510}
8511
8512INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8513{
8514 // TODO Implement me!
8515 return RETURN_OK;
8516}
8517
8518INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8519{
developera3c68b92022-09-13 15:27:29 +08008520 char file_name[128] = {0};
8521 char buf[128] = {0};
8522 FILE *f = NULL;
8523
8524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8525
8526 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8527 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8528 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8529 f = fopen(file_name, "w");
8530 if (f == NULL)
8531 return RETURN_ERR;
8532 // For mode == 0 is to disable filter, just don't write to the file.
8533 if (mode)
8534 fprintf(f, "%s", essid);
8535
8536 fclose(f);
8537 }
8538 } else { // special case, need to set AP's SSID as filter for each radio.
8539 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8540 f = fopen(file_name, "w");
8541 if (f == NULL)
8542 return RETURN_ERR;
8543
8544 // For mode == 0 is to disable filter, just don't write to the file.
8545 if (mode)
8546 fprintf(f, "%s", essid);
8547
8548 fclose(f);
8549 }
8550
8551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008552 return RETURN_OK;
8553}
8554
8555INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8556{
8557 // TODO Implement me!
8558 //Apply wifi_pushRadioChannel() instantly
8559 return RETURN_ERR;
8560}
8561
8562INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8563{
8564 // TODO Implement me!
8565 return RETURN_OK;
8566}
8567
8568#ifdef HAL_NETLINK_IMPL
8569static int tidStats_callback(struct nl_msg *msg, void *arg) {
8570 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8571 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8572 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8573 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8574 int rem , tid_index = 0;
8575
8576 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8577 wifi_associated_dev_tid_entry_t *stats_entry;
8578
8579 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8580 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8581 };
8582 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8583 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8584 };
8585
8586 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8587 genlmsg_attrlen(gnlh, 0), NULL);
8588
8589
8590 if (!tb[NL80211_ATTR_STA_INFO]) {
8591 fprintf(stderr, "station stats missing!\n");
8592 return NL_SKIP;
8593 }
8594
8595 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8596 tb[NL80211_ATTR_STA_INFO],
8597 stats_policy)) {
8598 fprintf(stderr, "failed to parse nested attributes!\n");
8599 return NL_SKIP;
8600 }
8601
8602 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8603 {
8604 stats_entry = &out->tid_array[tid_index];
8605
8606 stats_entry->tid = tid_index;
8607 stats_entry->ac = _tid_ac_index_get[tid_index];
8608
8609 if(sinfo[NL80211_STA_INFO_TID_STATS])
8610 {
8611 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8612 printf("failed to parse nested stats attributes!");
8613 return NL_SKIP;
8614 }
8615 }
8616 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8617 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8618
8619 if(tid_index < (PS_MAX_TID - 1))
8620 tid_index++;
8621 }
8622 //ToDo: sum_time_ms, ewma_time_ms
8623 return NL_SKIP;
8624}
8625#endif
8626
8627INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8628{
8629#ifdef HAL_NETLINK_IMPL
8630 Netlink nl;
8631 char if_name[10];
8632
8633 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8634
8635 nl.id = initSock80211(&nl);
8636
8637 if (nl.id < 0) {
8638 fprintf(stderr, "Error initializing netlink \n");
8639 return -1;
8640 }
8641
8642 struct nl_msg* msg = nlmsg_alloc();
8643
8644 if (!msg) {
8645 fprintf(stderr, "Failed to allocate netlink message.\n");
8646 nlfree(&nl);
8647 return -2;
8648 }
8649
8650 genlmsg_put(msg,
8651 NL_AUTO_PORT,
8652 NL_AUTO_SEQ,
8653 nl.id,
8654 0,
8655 0,
8656 NL80211_CMD_GET_STATION,
8657 0);
8658
8659 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8660 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8661 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
8662 nl_send_auto(nl.socket, msg);
8663 nl_recvmsgs(nl.socket, nl.cb);
8664 nlmsg_free(msg);
8665 nlfree(&nl);
8666 return RETURN_OK;
8667#else
8668//iw implementation
8669#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
8670#define TOTAL_MAX_LINES 50
8671
8672 char buf[256] = {'\0'}; /* or other suitable maximum line size */
8673 char if_name[10];
8674 FILE *fp=NULL;
8675 char pipeCmd[1024]= {'\0'};
8676 int lines,tid_index=0;
8677 char mac_addr[20] = {'\0'};
8678
8679 wifi_associated_dev_tid_entry_t *stats_entry;
8680
8681 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8682 strcpy(mac_addr,clientMacAddress);
8683
8684 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
8685 fp= popen(pipeCmd,"r");
8686 if(fp == NULL)
8687 {
8688 perror("popen for station dump failed\n");
8689 return RETURN_ERR;
8690 }
8691 pclose(fp);
8692
8693 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
8694 fp=popen(pipeCmd,"r");
8695 if(fp == NULL)
8696 {
8697 perror("popen for grep station failed\n");
8698 return RETURN_ERR;
8699 }
8700 else if(fgets(buf,sizeof(buf),fp) != NULL)
8701 lines=atoi(buf);
8702 else
8703 {
8704 pclose(fp);
8705 fprintf(stderr,"No devices are connected \n");
8706 return RETURN_ERR;
8707 }
8708 pclose(fp);
8709
8710 if(lines == 1)
8711 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
8712
8713 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
8714 {
8715 stats_entry = &tid_stats->tid_array[tid_index];
8716 stats_entry->tid = tid_index;
8717
8718 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);
8719
8720 fp=popen(pipeCmd,"r");
8721 if(fp ==NULL)
8722 {
8723 perror("Failed to read from tid file \n");
8724 return RETURN_ERR;
8725 }
8726 else if(fgets(buf,sizeof(buf),fp) != NULL)
8727 stats_entry->num_msdus = atol(buf);
8728
8729 pclose(fp);
8730 stats_entry->ac = _tid_ac_index_get[tid_index];
8731// TODO:
8732// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
8733// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
8734 }
8735 return RETURN_OK;
8736#endif
8737}
8738
8739
8740INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
8741{
8742 // TODO Implement me!
8743 return RETURN_OK;
8744}
8745
8746
8747INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
8748{
8749 // TODO Implement me!
8750 return RETURN_ERR;
8751}
8752
8753INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
8754{
8755 // TODO Implement me!
8756 return RETURN_ERR;
8757}
8758
8759INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8760{
8761 // TODO Implement me!
8762 return RETURN_ERR;
8763}
8764
8765INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
8766{
8767 // TODO Implement me!
8768 return RETURN_ERR;
8769}
8770
8771INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
8772{
8773 // TODO Implement me!
8774 return RETURN_ERR;
8775}
8776
8777INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
8778{
8779 // TODO Implement me!
8780 return RETURN_ERR;
8781}
8782
8783INT wifi_steering_eventUnregister(void)
8784{
8785 // TODO Implement me!
8786 return RETURN_ERR;
8787}
8788
8789INT wifi_delApAclDevices(INT apIndex)
8790{
8791#if 0
8792 char cmd[MAX_BUF_SIZE] = {0};
8793 char buf[MAX_BUF_SIZE] = {0};
8794
8795 /* Not reset proof solution */
8796 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
8797 if(_syscmd(cmd,buf,sizeof(buf)))
8798 return RETURN_ERR;
8799#endif
developere6aafda2022-09-13 14:59:28 +08008800 char cmd[MAX_CMD_SIZE]={0};
8801 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08008802
developere6aafda2022-09-13 14:59:28 +08008803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8804 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
8805 if(_syscmd(cmd, buf, sizeof(buf)))
8806 return RETURN_ERR;
8807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008808
8809 return RETURN_OK;
8810}
8811
8812#ifdef HAL_NETLINK_IMPL
8813static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
8814 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8815 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8816 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8817 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8818 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8819 char mac_addr[20],dev[20];
8820
8821 nla_parse(tb,
8822 NL80211_ATTR_MAX,
8823 genlmsg_attrdata(gnlh, 0),
8824 genlmsg_attrlen(gnlh, 0),
8825 NULL);
8826
8827 if(!tb[NL80211_ATTR_STA_INFO]) {
8828 fprintf(stderr, "sta stats missing!\n");
8829 return NL_SKIP;
8830 }
8831
8832 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8833 fprintf(stderr, "failed to parse nested attributes!\n");
8834 return NL_SKIP;
8835 }
8836 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8837
8838 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8839
8840 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
8841 fprintf(stderr, "failed to parse nested rate attributes!");
8842 return NL_SKIP;
8843 }
8844
8845 if(sinfo[NL80211_STA_INFO_TID_STATS])
8846 {
8847 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8848 printf("failed to parse nested stats attributes!");
8849 return NL_SKIP;
8850 }
8851 }
8852
8853 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
8854 {
8855 printf("Type is VHT\n");
8856 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8857 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8858
8859 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8860 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
8861 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
8862 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8863 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
8864 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8865 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
8866 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
8867 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
8868 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8869 }
8870 else
8871 {
8872 printf(" OFDM or CCK \n");
8873 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
8874 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
8875 }
8876
8877 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
8878 if(rinfo[NL80211_RATE_INFO_MCS])
8879 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
8880 }
8881 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
8882 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
8883 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
8884 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
8885
8886 if(stats_info[NL80211_TID_STATS_RX_MSDU])
8887 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
8888
8889 if (sinfo[NL80211_STA_INFO_SIGNAL])
8890 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
8891 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
8892 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
8893 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
8894 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
8895 //rssi_array need to be filled
8896 return NL_SKIP;
8897}
8898#endif
8899
8900INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
8901{
8902#ifdef HAL_NETLINK_IMPL
8903 Netlink nl;
8904 char if_name[10];
8905
8906 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
8907
8908 if (*output_array_size <= 0)
8909 return RETURN_OK;
8910
8911 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8912 nl.id = initSock80211(&nl);
8913
8914 if (nl.id < 0) {
8915 fprintf(stderr, "Error initializing netlink \n");
8916 return 0;
8917 }
8918
8919 struct nl_msg* msg = nlmsg_alloc();
8920
8921 if (!msg) {
8922 fprintf(stderr, "Failed to allocate netlink message.\n");
8923 nlfree(&nl);
8924 return 0;
8925 }
8926
8927 genlmsg_put(msg,
8928 NL_AUTO_PORT,
8929 NL_AUTO_SEQ,
8930 nl.id,
8931 0,
8932 0,
8933 NL80211_CMD_GET_STATION,
8934 0);
8935
8936 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
8937 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8938 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
8939 nl_send_auto(nl.socket, msg);
8940 nl_recvmsgs(nl.socket, nl.cb);
8941 nlmsg_free(msg);
8942 nlfree(&nl);
8943 return RETURN_OK;
8944#else
8945 //TODO Implement me
8946 return RETURN_OK;
8947#endif
8948}
8949
8950#ifdef HAL_NETLINK_IMPL
8951static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
8952 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8953 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8954 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8955 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
8956 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
8957 char mac_addr[20],dev[20];
8958
8959 nla_parse(tb,
8960 NL80211_ATTR_MAX,
8961 genlmsg_attrdata(gnlh, 0),
8962 genlmsg_attrlen(gnlh, 0),
8963 NULL);
8964
8965 if(!tb[NL80211_ATTR_STA_INFO]) {
8966 fprintf(stderr, "sta stats missing!\n");
8967 return NL_SKIP;
8968 }
8969
8970 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
8971 fprintf(stderr, "failed to parse nested attributes!\n");
8972 return NL_SKIP;
8973 }
8974
8975 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
8976
8977 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
8978
8979 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
8980 fprintf(stderr, "failed to parse nested rate attributes!");
8981 return NL_SKIP;
8982 }
8983
8984 if(sinfo[NL80211_STA_INFO_TID_STATS])
8985 {
8986 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
8987 printf("failed to parse nested stats attributes!");
8988 return NL_SKIP;
8989 }
8990 }
8991 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
8992 {
8993 printf("Type is VHT\n");
8994 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
8995 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
8996
8997 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
8998 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
8999 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9000 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9001 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9002 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9003 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9004 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9005 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9006 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9007 }
9008 else
9009 {
9010 printf(" OFDM or CCK \n");
9011 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9012 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9013 }
9014
9015 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9016 if(rinfo[NL80211_RATE_INFO_MCS])
9017 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9018 }
9019
9020 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9021 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9022 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9023 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9024
9025 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9026 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9027 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9028
9029 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9030 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9031
9032 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9033 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9034
9035 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9036 ((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]);
9037
9038 return NL_SKIP;
9039}
9040#endif
9041
9042INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9043{
9044#ifdef HAL_NETLINK_IMPL
9045 Netlink nl;
9046 char if_name[10];
9047
9048 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9049
9050 if (*output_array_size <= 0)
9051 return RETURN_OK;
9052
9053 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9054
9055 nl.id = initSock80211(&nl);
9056
9057 if(nl.id < 0) {
9058 fprintf(stderr, "Error initializing netlink \n");
9059 return 0;
9060 }
9061
9062 struct nl_msg* msg = nlmsg_alloc();
9063
9064 if(!msg) {
9065 fprintf(stderr, "Failed to allocate netlink message.\n");
9066 nlfree(&nl);
9067 return 0;
9068 }
9069
9070 genlmsg_put(msg,
9071 NL_AUTO_PORT,
9072 NL_AUTO_SEQ,
9073 nl.id,
9074 0,
9075 0,
9076 NL80211_CMD_GET_STATION,
9077 0);
9078
9079 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9080 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9081 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9082 nl_send_auto(nl.socket, msg);
9083 nl_recvmsgs(nl.socket, nl.cb);
9084 nlmsg_free(msg);
9085 nlfree(&nl);
9086 return RETURN_OK;
9087#else
9088 //TODO Implement me
9089 return RETURN_OK;
9090#endif
9091}
9092
9093INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9094{
9095 // TODO Implement me!
9096 char buf[MAX_BUF_SIZE] = {0};
9097 char config_file[MAX_BUF_SIZE] = {0};
9098
9099 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9100 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9101 *activate = (strncmp("1",buf,1) == 0);
9102
9103 return RETURN_OK;
9104}
9105
9106INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9107{
9108 char config_file[MAX_BUF_SIZE] = {0};
9109 struct params list;
9110
9111 list.name = "rrm_neighbor_report";
9112 list.value = activate?"1":"0";
9113 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9114 wifi_hostapdWrite(config_file, &list, 1);
9115
9116 return RETURN_OK;
9117}
9118
9119INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9120{
9121 char buf[32] = {0};
9122 char config_file[MAX_BUF_SIZE] = {0};
9123
9124 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9125 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9126 *activate = (strncmp("1",buf,1) == 0);
9127
9128 return RETURN_OK;
9129}
9130#undef HAL_NETLINK_IMPL
9131#ifdef HAL_NETLINK_IMPL
9132static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9133 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9134 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9135 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9136 char dev[20];
9137 int freq =0 ;
9138 static int i=0;
9139
9140 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9141
9142 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9143 };
9144
9145 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9146
9147 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9148
9149 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9150 fprintf(stderr, "survey data missing!\n");
9151 return NL_SKIP;
9152 }
9153
9154 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9155 {
9156 fprintf(stderr, "failed to parse nested attributes!\n");
9157 return NL_SKIP;
9158 }
9159
9160
9161 if(out[0].array_size == 1 )
9162 {
9163 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9164 {
9165 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9166 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9167 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9168
9169 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9170 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9171 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9172 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9173 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9174 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9175 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9176 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9177 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9178 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9179 if (sinfo[NL80211_SURVEY_INFO_TIME])
9180 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9181 return NL_STOP;
9182 }
9183 }
9184 else
9185 {
9186 if ( i <= out[0].array_size )
9187 {
9188 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9189 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9190 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9191
9192 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9193 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9194 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9195 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9196 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9197 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9198 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9199 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9200 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9201 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9202 if (sinfo[NL80211_SURVEY_INFO_TIME])
9203 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9204 }
9205 }
9206
9207 i++;
9208 return NL_SKIP;
9209}
9210#endif
9211
9212static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9213{
9214 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9215 FILE *fp;
9216
9217 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9218 {
9219 printf("Creating Frequency-Channel Map\n");
9220 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9221 }
9222 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9223 if((fp = popen(command, "r")))
9224 {
9225 fgets(output, sizeof(output), fp);
9226 *freqMHz = atoi(output);
9227 fclose(fp);
9228 }
9229
9230 return 0;
9231}
9232
9233static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9234{
9235 int freqMHz = -1;
9236 char cmd[MAX_CMD_SIZE] = {'\0'};
9237
9238 ieee80211_channel_to_frequency(channel, &freqMHz);
9239 if (freqMHz == -1) {
9240 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9241 return -1;
9242 }
9243
9244 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9245 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9246 radioIndex, freqMHz);
9247 return -1;
9248 }
9249
9250 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9251 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9252 return -1;
9253 }
9254
9255 return 0;
9256}
9257
9258static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9259{
9260 const char *ptr = buf;
9261 char *key = NULL;
9262 char *val = NULL;
9263 char line[256] = { '\0' };
9264
9265 while (ptr = get_line_from_str_buf(ptr, line)) {
9266 if (strstr(line, "Frequency")) continue;
9267
9268 key = strtok(line, ":");
9269 val = strtok(NULL, " ");
9270 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9271
9272 if (!strcmp(key, "noise")) {
9273 sscanf(val, "%d", &stats->ch_noise);
9274 if (stats->ch_noise == 0) {
9275 // Workaround for missing noise information.
9276 // Assume -95 for 2.4G and -103 for 5G
9277 if (radioIndex == 0) stats->ch_noise = -95;
9278 if (radioIndex == 1) stats->ch_noise = -103;
9279 }
9280 }
9281 else if (!strcmp(key, "channel active time")) {
9282 sscanf(val, "%llu", &stats->ch_utilization_total);
9283 }
9284 else if (!strcmp(key, "channel busy time")) {
9285 sscanf(val, "%llu", &stats->ch_utilization_busy);
9286 }
9287 else if (!strcmp(key, "channel receive time")) {
9288 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9289 }
9290 else if (!strcmp(key, "channel transmit time")) {
9291 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9292 }
9293 };
9294
9295 return 0;
9296}
9297
9298INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9299{
9300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9301#ifdef HAL_NETLINK_IMPL
9302 Netlink nl;
9303 wifi_channelStats_t_loc local[array_size];
9304 char if_name[10];
9305
9306 local[0].array_size = array_size;
9307
9308 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9309
9310 nl.id = initSock80211(&nl);
9311
9312 if (nl.id < 0) {
9313 fprintf(stderr, "Error initializing netlink \n");
9314 return -1;
9315 }
9316
9317 struct nl_msg* msg = nlmsg_alloc();
9318
9319 if (!msg) {
9320 fprintf(stderr, "Failed to allocate netlink message.\n");
9321 nlfree(&nl);
9322 return -2;
9323 }
9324
9325 genlmsg_put(msg,
9326 NL_AUTO_PORT,
9327 NL_AUTO_SEQ,
9328 nl.id,
9329 0,
9330 NLM_F_DUMP,
9331 NL80211_CMD_GET_SURVEY,
9332 0);
9333
9334 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9335 nl_send_auto(nl.socket, msg);
9336 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9337 nl_recvmsgs(nl.socket, nl.cb);
9338 nlmsg_free(msg);
9339 nlfree(&nl);
9340 //Copying the Values
9341 for(int i=0;i<array_size;i++)
9342 {
9343 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9344 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9345 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9346 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9347 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9348 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9349 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9350 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9351 }
9352#else
9353 ULONG channel = 0;
9354 int i;
9355 int number_of_channels = array_size;
9356 char buf[512];
9357 INT ret;
9358 wifi_channelStats_t tmp_stats;
9359
9360 if (number_of_channels == 0) {
9361 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9362 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9363 return RETURN_ERR;
9364 }
9365 number_of_channels = 1;
9366 input_output_channelStats_array[0].ch_number = channel;
9367 }
9368
9369 for (i = 0; i < number_of_channels; i++) {
9370
9371 input_output_channelStats_array[i].ch_noise = 0;
9372 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9373 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9374 input_output_channelStats_array[i].ch_utilization_busy = 0;
9375 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9376 input_output_channelStats_array[i].ch_utilization_total = 0;
9377
9378 memset(buf, 0, sizeof(buf));
9379 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9380 return RETURN_ERR;
9381 }
9382 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9383 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9384 return RETURN_ERR;
9385 }
9386
9387 // XXX: fake missing 'self' counter which is not available in iw survey output
9388 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9389 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9390
9391 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9392 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9393 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9394 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9395 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9396
9397 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",
9398 __func__,
9399 input_output_channelStats_array[i].ch_number,
9400 input_output_channelStats_array[i].ch_noise,
9401 input_output_channelStats_array[i].ch_utilization_total,
9402 input_output_channelStats_array[i].ch_utilization_busy,
9403 input_output_channelStats_array[i].ch_utilization_busy_rx,
9404 input_output_channelStats_array[i].ch_utilization_busy_tx,
9405 input_output_channelStats_array[i].ch_utilization_busy_self,
9406 input_output_channelStats_array[i].ch_utilization_busy_ext);
9407 }
9408#endif
9409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9410 return RETURN_OK;
9411}
9412#define HAL_NETLINK_IMPL
9413
9414/* Hostapd events */
9415
9416#ifndef container_of
9417#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9418#define container_of(ptr, type, member) \
9419 ((type *)((char *)ptr - offset_of(type, member)))
9420#endif /* container_of */
9421
9422struct ctrl {
9423 char sockpath[128];
9424 char sockdir[128];
9425 char bss[IFNAMSIZ];
9426 char reply[4096];
9427 int ssid_index;
9428 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9429 void (*overrun)(struct ctrl *ctrl);
9430 struct wpa_ctrl *wpa;
9431 unsigned int ovfl;
9432 size_t reply_len;
9433 int initialized;
9434 ev_timer retry;
9435 ev_timer watchdog;
9436 ev_stat stat;
9437 ev_io io;
9438};
9439static wifi_newApAssociatedDevice_callback clients_connect_cb;
9440static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9441static struct ctrl wpa_ctrl[MAX_APS];
9442static int initialized;
9443
9444static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9445{
9446 char cbuf[256] = {};
9447 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9448 struct cmsghdr *cmsg;
9449 unsigned int ovfl = ctrl->ovfl;
9450 unsigned int drop;
9451
9452 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9453 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9454 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9455 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9456
9457 drop = ovfl - ctrl->ovfl;
9458 ctrl->ovfl = ovfl;
9459
9460 return drop;
9461}
9462
9463static void ctrl_close(struct ctrl *ctrl)
9464{
9465 if (ctrl->io.cb)
9466 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9467 if (ctrl->retry.cb)
9468 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9469 if (!ctrl->wpa)
9470 return;
9471
9472 wpa_ctrl_detach(ctrl->wpa);
9473 wpa_ctrl_close(ctrl->wpa);
9474 ctrl->wpa = NULL;
9475 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9476}
9477
9478static void ctrl_process(struct ctrl *ctrl)
9479{
9480 const char *str;
9481 int drops;
9482 int level;
9483 int err;
9484
9485 /* Example events:
9486 *
9487 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9488 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9489 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9490 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9491 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9492 */
9493 if (!(str = index(ctrl->reply, '>')))
9494 return;
9495 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9496 return;
9497
9498 str++;
9499
9500 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9501 if (!(str = index(ctrl->reply, ' ')))
9502 return;
9503 wifi_associated_dev_t sta;
9504 memset(&sta, 0, sizeof(sta));
9505
9506 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9507 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9508 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9509
9510 sta.cli_Active=true;
9511
9512 (clients_connect_cb)(ctrl->ssid_index, &sta);
9513 goto handled;
9514 }
9515
9516 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9517 if (!(str = index(ctrl->reply, ' ')))
9518 return;
9519
9520 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9521 goto handled;
9522 }
9523
9524 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9525 printf("CTRL_WPA: handle TERMINATING event\n");
9526 goto retry;
9527 }
9528
9529 if (strncmp("AP-DISABLED", str, 11) == 0) {
9530 printf("CTRL_WPA: handle AP-DISABLED\n");
9531 goto retry;
9532 }
9533
9534 printf("Event not supported!!\n");
9535
9536handled:
9537
9538 if ((drops = ctrl_get_drops(ctrl))) {
9539 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9540 if (ctrl->overrun)
9541 ctrl->overrun(ctrl);
9542 }
9543
9544 return;
9545
9546retry:
9547 printf("WPA_CTRL: closing\n");
9548 ctrl_close(ctrl);
9549 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9550 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9551}
9552
9553static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9554{
9555 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9556 int err;
9557
9558 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9559 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9560 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9561 ctrl->reply[ctrl->reply_len] = 0;
9562 if (err < 0) {
9563 if (errno == EAGAIN || errno == EWOULDBLOCK)
9564 return;
9565 ctrl_close(ctrl);
9566 ev_timer_again(EV_A_ &ctrl->retry);
9567 return;
9568 }
9569
9570 ctrl_process(ctrl);
9571}
9572
9573static int ctrl_open(struct ctrl *ctrl)
9574{
9575 int fd;
9576
9577 if (ctrl->wpa)
9578 return 0;
9579
9580 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9581 if (!ctrl->wpa)
9582 goto err;
9583
9584 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9585 goto err_close;
9586
9587 fd = wpa_ctrl_get_fd(ctrl->wpa);
9588 if (fd < 0)
9589 goto err_detach;
9590
9591 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9592 goto err_detach;
9593
9594 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9595 ev_io_start(EV_DEFAULT_ &ctrl->io);
9596
9597 return 0;
9598
9599err_detach:
9600 wpa_ctrl_detach(ctrl->wpa);
9601err_close:
9602 wpa_ctrl_close(ctrl->wpa);
9603err:
9604 ctrl->wpa = NULL;
9605 return -1;
9606}
9607
9608static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9609{
9610 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9611
9612 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9613 ctrl_open(ctrl);
9614}
9615
9616static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9617{
9618 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9619
9620 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9621 if (ctrl_open(ctrl) == 0) {
9622 printf("WPA_CTRL: retry successful\n");
9623 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9624 }
9625}
9626
9627int ctrl_enable(struct ctrl *ctrl)
9628{
9629 if (ctrl->wpa)
9630 return 0;
9631
9632 if (!ctrl->stat.cb) {
9633 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9634 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
9635 }
9636
9637 if (!ctrl->retry.cb) {
9638 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
9639 }
9640
9641 return ctrl_open(ctrl);
9642}
9643
9644static void
9645ctrl_msg_cb(char *buf, size_t len)
9646{
9647 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
9648
9649 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
9650 ctrl_process(ctrl);
9651}
9652
9653static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
9654{
9655 int err;
9656
9657 if (!ctrl->wpa)
9658 return -1;
9659 if (*reply_len < 2)
9660 return -1;
9661
9662 (*reply_len)--;
9663 ctrl->reply_len = sizeof(ctrl->reply);
9664 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
9665 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
9666 if (err < 0)
9667 return err;
9668
9669 if (ctrl->reply_len > *reply_len)
9670 ctrl->reply_len = *reply_len;
9671
9672 *reply_len = ctrl->reply_len;
9673 memcpy(reply, ctrl->reply, *reply_len);
9674 reply[*reply_len - 1] = 0;
9675 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
9676 return 0;
9677}
9678
9679static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
9680{
9681 const char *pong = "PONG";
9682 const char *ping = "PING";
9683 char reply[1024];
9684 size_t len = sizeof(reply);
9685 int err;
9686 ULONG s, snum;
9687 INT ret;
9688 BOOL status;
9689
9690 printf("WPA_CTRL: watchdog cb\n");
9691
9692 ret = wifi_getSSIDNumberOfEntries(&snum);
9693 if (ret != RETURN_OK) {
9694 printf("%s: failed to get SSID count", __func__);
9695 return;
9696 }
9697
9698 if (snum > MAX_APS) {
9699 printf("more ssid than supported! %lu\n", snum);
9700 return;
9701 }
9702
9703 for (s = 0; s < snum; s++) {
9704 if (wifi_getApEnable(s, &status) != RETURN_OK) {
9705 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
9706 continue;
9707 }
9708 if (status == false) continue;
9709
9710 memset(reply, 0, sizeof(reply));
9711 len = sizeof(reply);
9712 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
9713 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
9714 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
9715 continue;
9716
9717 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
9718 ctrl_close(&wpa_ctrl[s]);
9719 printf("WPA_CTRL: ev_timer_again %d\n", s);
9720 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
9721 }
9722}
9723
9724static int init_wpa()
9725{
9726 int ret = 0, i = 0;
9727 ULONG s, snum;
9728
9729 ret = wifi_getSSIDNumberOfEntries(&snum);
9730 if (ret != RETURN_OK) {
9731 printf("%s: failed to get SSID count", __func__);
9732 return RETURN_ERR;
9733 }
9734
9735 if (snum > MAX_APS) {
9736 printf("more ssid than supported! %lu\n", snum);
9737 return RETURN_ERR;
9738 }
9739
9740 for (s = 0; s < snum; s++) {
9741 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
9742 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
9743 wpa_ctrl[s].ssid_index = s;
9744 ctrl_enable(&wpa_ctrl[s]);
9745 }
9746
9747 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
9748 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
9749
9750 initialized = 1;
9751 printf("WPA_CTRL: initialized\n");
9752
9753 return RETURN_OK;
9754}
9755
9756void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
9757{
9758 clients_connect_cb = callback_proc;
9759 if (!initialized)
9760 init_wpa();
9761}
9762
9763void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
9764{
9765 clients_disconnect_cb = callback_proc;
9766 if (!initialized)
9767 init_wpa();
9768}
9769
9770INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
9771{
9772 // TODO Implement me!
9773 return RETURN_ERR;
9774}
9775
9776INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
9777{
9778 // TODO Implement me!
9779 return RETURN_ERR;
9780}
9781
9782INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
9783{
9784 int i;
9785 char cmd[256];
9786 char channel_numbers_buf[256];
9787 char dfs_state_buf[256];
9788 char line[256];
9789 const char *ptr;
9790
9791 memset(cmd, 0, sizeof(cmd));
9792 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
9793 memset(line, 0, sizeof(line));
9794 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9795 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
9796
9797 if (radioIndex == 0) { // 2.4G - all allowed
9798 if (outputMapSize < 11) {
9799 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
9800 return RETURN_ERR;
9801 }
9802
9803 for (i = 0; i < 11; i++) {
9804 outputMap[i].ch_number = i + 1;
9805 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9806 }
9807
9808 return RETURN_OK;
9809 }
9810
9811 if (radioIndex == 1) { // 5G
9812// Example output of iw list:
9813//
9814// Frequencies:
9815// * 5180 MHz [36] (17.0 dBm)
9816// * 5200 MHz [40] (17.0 dBm)
9817// * 5220 MHz [44] (17.0 dBm)
9818// * 5240 MHz [48] (17.0 dBm)
9819// * 5260 MHz [52] (23.0 dBm) (radar detection)
9820// DFS state: usable (for 78930 sec)
9821// DFS CAC time: 60000 ms
9822// * 5280 MHz [56] (23.0 dBm) (radar detection)
9823// DFS state: usable (for 78930 sec)
9824// DFS CAC time: 60000 ms
9825// * 5300 MHz [60] (23.0 dBm) (radar detection)
9826// DFS state: usable (for 78930 sec)
9827// DFS CAC time: 60000 ms
9828// * 5320 MHz [64] (23.0 dBm) (radar detection)
9829// DFS state: usable (for 78930 sec)
9830// DFS CAC time: 60000 ms
9831// * 5500 MHz [100] (disabled)
9832// * 5520 MHz [104] (disabled)
9833// * 5540 MHz [108] (disabled)
9834// * 5560 MHz [112] (disabled)
9835//
9836// Below command should fetch channel numbers of each enabled channel in 5GHz band:
9837 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
9838 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
9839 return RETURN_ERR;
9840 }
9841
9842 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
9843 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9844 return RETURN_ERR;
9845 }
9846
9847 ptr = channel_numbers_buf;
9848 i = 0;
9849 while (ptr = get_line_from_str_buf(ptr, line)) {
9850 if (i >= outputMapSize) {
9851 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
9852 return RETURN_ERR;
9853 }
9854 sscanf(line, "%d", &outputMap[i].ch_number);
9855
9856 memset(cmd, 0, sizeof(cmd));
9857 // Below command should fetch string for DFS state (usable, available or unavailable)
9858 // Example line: "DFS state: usable (for 78930 sec)"
9859 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) {
9860 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
9861 return RETURN_ERR;
9862 }
9863
9864 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
9865 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
9866 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9867 return RETURN_ERR;
9868 }
9869
9870 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
9871
9872 if (!strcmp(dfs_state_buf, "usable")) {
9873 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
9874 } else if (!strcmp(dfs_state_buf, "available")) {
9875 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
9876 } else if (!strcmp(dfs_state_buf, "unavailable")) {
9877 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
9878 } else {
9879 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
9880 }
9881 i++;
9882 }
9883
9884 return RETURN_OK;
9885 }
9886
9887 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
9888 return RETURN_ERR;
9889}
9890
9891INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
9892{
9893 // TODO Implement me!
9894 return RETURN_ERR;
9895}
9896
9897INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
9898{
9899 return RETURN_OK;
9900}
9901
9902INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
9903{
9904 // TODO Implement me!
9905 return RETURN_ERR;
9906}
9907
9908INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
9909{
9910 // TODO API refrence Implementaion is present on RPI hal
9911 return RETURN_ERR;
9912}
9913
9914INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
9915{
developera5005b62022-09-13 15:43:35 +08009916 char cmd[128]={'\0'};
9917 char buf[128]={'\0'};
9918 char *support;
9919 int maximum_tx = 0, current_tx = 0;
9920
9921 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9922 if(txpwr_pcntg == NULL)
9923 return RETURN_ERR;
9924
9925 // Get the maximum tx power of the device
9926 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
9927 _syscmd(cmd, buf, sizeof(buf));
9928 maximum_tx = strtol(buf, NULL, 10);
9929
9930 // Get the current tx power
9931 memset(cmd, 0, sizeof(cmd));
9932 memset(buf, 0, sizeof(buf));
9933 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
9934 _syscmd(cmd, buf, sizeof(buf));
9935 current_tx = strtol(buf, NULL, 10);
9936
9937 // Get the power supported list and find the current power percentage in supported list
9938 memset(buf, 0, sizeof(buf));
9939 wifi_getRadioTransmitPowerSupported(apIndex, buf);
9940 support = strtok(buf, ",");
9941 while(true)
9942 {
9943 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
9944 *txpwr_pcntg = 0;
9945 wifi_dbg_printf("current power is not in supported list\n");
9946 return RETURN_ERR;
9947 }
9948 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
9949 if (tmp == current_tx) {
9950 *txpwr_pcntg = strtol(support, NULL, 10);
9951 break;
9952 }
9953 support = strtok(NULL, ",");
9954 }
9955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009956 return RETURN_OK;
9957}
9958
9959INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
9960{
9961 //Zero-wait DFS not supported
9962 return RETURN_ERR;
9963}
9964
9965INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
9966{
9967 //Zero-wait DFS not supported
9968 return RETURN_ERR;
9969}
9970
9971INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
9972{
9973 *supported = false;
9974 return RETURN_OK;
9975}
9976
developer454b9462022-09-13 15:29:16 +08009977INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
9978{
9979 char cmd[128] = {0};
9980 char buf[64] = {0};
9981 char band_str[8] = {0};
9982 char GI[8] = {0};
9983 int tmp = 0;
9984 BOOL ax_mode = FALSE;
9985 BOOL short_GI = FALSE;
9986 FILE *f = NULL;
9987 wifi_band band;
9988
9989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9990
9991 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
9992 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
9993 return RETURN_ERR;
9994 }
9995 if (strstr(buf, "ax") != NULL)
9996 ax_mode = TRUE;
9997
9998 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
9999 short_GI = TRUE;
10000 strcpy(GI, "0.4");
10001 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10002 strcpy(GI, "1.6");
10003 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10004 strcpy(GI, "3.2");
10005 else // default
10006 strcpy(GI, "0.8");
10007
10008 band = wifi_index_to_band(radio_index);
10009 if (band == band_2_4)
10010 strcpy(band_str, "2.4");
10011 else if (band == band_5)
10012 strcpy(band_str, "5");
10013 else if (band == band_6)
10014 strcpy(band_str, "6");
10015 else {
10016 wifi_dbg_printf("%s: invalid band\n");
10017 return RETURN_ERR;
10018 }
10019
10020 if (ax_mode == TRUE)
10021 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10022 else
10023 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10024 _syscmd(cmd, buf, sizeof(buf));
10025
10026 // Record GI for get GI function
10027 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10028 f = fopen(buf, "w");
10029 if (f != NULL) {
10030 fprintf(f, "%s", GI);
10031 }
10032 fclose(f);
10033 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10034 return RETURN_OK;
10035}
10036
10037INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10038{
10039 char buf[32] = {0};
10040 char cmd[64] = {0};
10041
10042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10043
10044 if (guard_interval == NULL)
10045 return RETURN_ERR;
10046
10047 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10048 _syscmd(cmd, buf, sizeof(buf));
10049
10050 if (strncmp(buf, "0.4", 3) == 0)
10051 *guard_interval = wifi_guard_interval_400;
10052 else if (strncmp(buf, "0.8", 3) == 0)
10053 *guard_interval = wifi_guard_interval_800;
10054 else if (strncmp(buf, "1.6", 3) == 0)
10055 *guard_interval = wifi_guard_interval_1600;
10056 else if (strncmp(buf, "3.2", 3) == 0)
10057 *guard_interval = wifi_guard_interval_3200;
10058 else
10059 *guard_interval = wifi_guard_interval_auto;
10060
10061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10062 return RETURN_OK;
10063}
10064
developer06a01d92022-09-07 16:32:39 +080010065/* multi-psk support */
10066INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10067{
10068 char cmd[256];
10069
10070 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10071 AP_PREFIX,
10072 apIndex,
10073 mac[0],
10074 mac[1],
10075 mac[2],
10076 mac[3],
10077 mac[4],
10078 mac[5]
10079 );
10080 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10081 _syscmd(cmd, key->wifi_keyId, 64);
10082
10083
10084 return RETURN_OK;
10085}
10086
10087INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10088{
10089 FILE *fd = NULL;
10090 char fname[100];
10091 char cmd[128] = {0};
10092 char out[64] = {0};
10093 wifi_key_multi_psk_t * key = NULL;
10094 if(keysNumber < 0)
10095 return RETURN_ERR;
10096
10097 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10098 fd = fopen(fname, "w");
10099 if (!fd) {
10100 return RETURN_ERR;
10101 }
10102 key= (wifi_key_multi_psk_t *) keys;
10103 for(int i=0; i<keysNumber; ++i, key++) {
10104 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10105 }
10106 fclose(fd);
10107
10108 //reload file
10109 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10110 _syscmd(cmd, out, 64);
10111 return RETURN_OK;
10112}
10113
10114INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10115{
10116 FILE *fd = NULL;
10117 char fname[100];
10118 char * line = NULL;
10119 char * pos = NULL;
10120 size_t len = 0;
10121 ssize_t read = 0;
10122 INT ret = RETURN_OK;
10123 wifi_key_multi_psk_t *keys_it = NULL;
10124
10125 if (keysNumber < 1) {
10126 return RETURN_ERR;
10127 }
10128
10129 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10130 fd = fopen(fname, "r");
10131 if (!fd) {
10132 return RETURN_ERR;
10133 }
10134
10135 if (keys == NULL) {
10136 ret = RETURN_ERR;
10137 goto close;
10138 }
10139
10140 keys_it = keys;
10141 while ((read = getline(&line, &len, fd)) != -1) {
10142 //Strip trailing new line if present
10143 if (read > 0 && line[read-1] == '\n') {
10144 line[read-1] = '\0';
10145 }
10146
10147 if(strcmp(line,"keyid=")) {
10148 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10149 if (!(pos = index(line, ' '))) {
10150 ret = RETURN_ERR;
10151 goto close;
10152 }
10153 pos++;
10154 //Here should be 00:00:00:00:00:00
10155 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10156 printf("Not supported MAC: %s\n", pos);
10157 }
10158 if (!(pos = index(pos, ' '))) {
10159 ret = RETURN_ERR;
10160 goto close;
10161 }
10162 pos++;
10163
10164 //The rest is PSK
10165 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10166 keys_it++;
10167
10168 if(--keysNumber <= 0)
10169 break;
10170 }
10171 }
10172
10173close:
10174 free(line);
10175 fclose(fd);
10176 return ret;
10177}
10178/* end of multi-psk support */
10179
10180INT wifi_setNeighborReports(UINT apIndex,
10181 UINT numNeighborReports,
10182 wifi_NeighborReport_t *neighborReports)
10183{
10184 char cmd[256] = { 0 };
10185 char hex_bssid[13] = { 0 };
10186 char bssid[18] = { 0 };
10187 char nr[256] = { 0 };
10188 char ssid[256];
10189 char hex_ssid[256];
10190 INT ret;
10191
10192 /*rmeove all neighbors*/
10193 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10194 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);
10195 system(cmd);
10196
10197 for(unsigned int i = 0; i < numNeighborReports; i++)
10198 {
10199 memset(ssid, 0, sizeof(ssid));
10200 ret = wifi_getSSIDName(apIndex, ssid);
10201 if (ret != RETURN_OK)
10202 return RETURN_ERR;
10203
10204 memset(hex_ssid, 0, sizeof(hex_ssid));
10205 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10206 sprintf(hex_ssid + k,"%02x", ssid[j]);
10207
10208 snprintf(hex_bssid, sizeof(hex_bssid),
10209 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10210 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10211 snprintf(bssid, sizeof(bssid),
10212 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10213 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10214
10215 snprintf(nr, sizeof(nr),
10216 "%s" // bssid
10217 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10218 "%02hhx" // operclass
10219 "%02hhx" // channel
10220 "%02hhx", // phy_mode
10221 hex_bssid,
10222 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10223 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10224 neighborReports[i].opClass,
10225 neighborReports[i].channel,
10226 neighborReports[i].phyTable);
10227
10228 snprintf(cmd, sizeof(cmd),
10229 "hostapd_cli set_neighbor "
10230 "%s " // bssid
10231 "ssid=%s " // ssid
10232 "nr=%s " // nr
10233 "-i %s%d",
10234 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10235
10236 if (WEXITSTATUS(system(cmd)) != 0)
10237 {
10238 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10239 }
10240 }
10241
10242 return RETURN_OK;
10243}
10244
10245INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10246{
10247 return RETURN_OK;
10248}
10249
10250#ifdef _WIFI_HAL_TEST_
10251int main(int argc,char **argv)
10252{
10253 int index;
10254 INT ret=0;
10255 char buf[1024]="";
10256
10257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10258 if(argc<3)
10259 {
10260 if(argc==2)
10261 {
10262 if(!strcmp(argv[1], "init"))
10263 return wifi_init();
10264 if(!strcmp(argv[1], "reset"))
10265 return wifi_reset();
10266 if(!strcmp(argv[1], "wifi_getHalVersion"))
10267 {
10268 char buffer[64];
10269 if(wifi_getHalVersion(buffer)==RETURN_OK)
10270 printf("Version: %s\n", buffer);
10271 else
10272 printf("Error in wifi_getHalVersion\n");
10273 return RETURN_OK;
10274 }
10275 }
10276 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10277 exit(-1);
10278 }
10279
10280 index = atoi(argv[2]);
10281 if(strstr(argv[1], "wifi_getApName")!=NULL)
10282 {
10283 wifi_getApName(index,buf);
10284 printf("Ap name is %s \n",buf);
10285 return 0;
10286 }
10287 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10288 {
10289 BOOL b = FALSE;
10290 BOOL *output_bool = &b;
10291 wifi_getRadioAutoChannelEnable(index,output_bool);
10292 printf("Channel enabled = %d \n",b);
10293 return 0;
10294 }
10295 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10296 {
10297 wifi_getApWpaEncryptionMode(index,buf);
10298 printf("encryption enabled = %s\n",buf);
10299 return 0;
10300 }
10301 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10302 {
10303 BOOL b = FALSE;
10304 BOOL *output_bool = &b;
10305 wifi_getApSsidAdvertisementEnable(index,output_bool);
10306 printf("advertisment enabled = %d\n",b);
10307 return 0;
10308 }
10309 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10310 {
10311 if(argc <= 3 )
10312 {
10313 printf("Insufficient arguments \n");
10314 exit(-1);
10315 }
10316
10317 char sta[20] = {'\0'};
10318 ULLONG handle= 0;
10319 strcpy(sta,argv[3]);
10320 mac_address_t st;
10321 mac_addr_aton(st,sta);
10322
10323 wifi_associated_dev_tid_stats_t tid_stats;
10324 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10325 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10326 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);
10327 }
10328
10329 if(strstr(argv[1], "getApEnable")!=NULL) {
10330 BOOL enable;
10331 ret=wifi_getApEnable(index, &enable);
10332 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10333 }
10334 else if(strstr(argv[1], "setApEnable")!=NULL) {
10335 BOOL enable = atoi(argv[3]);
10336 ret=wifi_setApEnable(index, enable);
10337 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10338 }
10339 else if(strstr(argv[1], "getApStatus")!=NULL) {
10340 char status[64];
10341 ret=wifi_getApStatus(index, status);
10342 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10343 }
10344 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10345 {
10346 wifi_getSSIDNameStatus(index,buf);
10347 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10348 return 0;
10349 }
10350 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10351 wifi_ssidTrafficStats2_t stats={0};
10352 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10353 printf("%s %d: returns %d\n", argv[1], index, ret);
10354 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10355 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10356 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10357 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10358 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10359 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10360 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10361 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10362 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10363 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10364 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10365 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10366 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10367 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10368 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10369 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10370 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10371 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10372 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10373 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10374 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10375 }
10376 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10377 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10378 UINT array_size=0;
10379 UINT i=0;
10380 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10381 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10382 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10383 printf(" neighbor %d:\n", i);
10384 printf(" ap_SSID =%s\n", pt->ap_SSID);
10385 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10386 printf(" ap_Mode =%s\n", pt->ap_Mode);
10387 printf(" ap_Channel =%d\n", pt->ap_Channel);
10388 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10389 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10390 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10391 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10392 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10393 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10394 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10395 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10396 printf(" ap_Noise =%d\n", pt->ap_Noise);
10397 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10398 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10399 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10400 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10401 }
10402 if(neighbor_ap_array)
10403 free(neighbor_ap_array); //make sure to free the list
10404 }
10405 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10406 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10407 UINT array_size=0;
10408 UINT i=0;
10409 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10410 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10411 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10412 printf(" associated_dev %d:\n", i);
10413 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10414 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10415 printf(" cli_SNR =%d\n", pt->cli_SNR);
10416 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10417 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10418 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10419 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10420 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10421 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10422 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10423 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10424 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10425 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10426 }
10427 if(associated_dev_array)
10428 free(associated_dev_array); //make sure to free the list
10429 }
10430
10431 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10432 {
10433#define MAX_ARRAY_SIZE 64
10434 int i, array_size;
10435 char *p, *ch_str;
10436 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10437
10438 if(argc != 5)
10439 {
10440 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10441 exit(-1);
10442 }
10443 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10444
10445 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10446 {
10447 strtok_r(ch_str, ",", &p);
10448 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10449 }
10450 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10451 if(!array_size)
10452 array_size=1;//Need to print current channel statistics
10453 for(i=0; i<array_size; i++)
10454 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10455 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10456 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10457 input_output_channelStats_array[i].ch_number,\
10458 input_output_channelStats_array[i].ch_noise,\
10459 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10460 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10461 input_output_channelStats_array[i].ch_utilization_busy,\
10462 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10463 input_output_channelStats_array[i].ch_utilization_total);
10464 }
10465
10466 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10467 {
10468 if(argc <= 3 )
10469 {
10470 printf("Insufficient arguments \n");
10471 exit(-1);
10472 }
10473 char mac_addr[20] = {'\0'};
10474 wifi_device_t output_struct;
10475 int dev_index = atoi(argv[3]);
10476
10477 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10478 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10479 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);
10480 }
10481
10482 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10483 {
10484 if (argc <= 3)
10485 {
10486 printf("Insufficient arguments\n");
10487 exit(-1);
10488 }
10489 char args[256];
10490 wifi_NeighborReport_t *neighborReports;
10491
10492 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10493 if (!neighborReports)
10494 {
10495 printf("Failed to allocate memory");
10496 exit(-1);
10497 }
10498
10499 for (int i = 3; i < argc; ++i)
10500 {
10501 char *val;
10502 int j = 0;
10503 memset(args, 0, sizeof(args));
10504 strncpy(args, argv[i], sizeof(args));
10505 val = strtok(args, ";");
10506 while (val != NULL)
10507 {
10508 if (j == 0)
10509 {
10510 mac_addr_aton(neighborReports[i - 3].bssid, val);
10511 } else if (j == 1)
10512 {
10513 neighborReports[i - 3].info = strtol(val, NULL, 16);
10514 } else if (j == 2)
10515 {
10516 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10517 } else if (j == 3)
10518 {
10519 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10520 } else if (j == 4)
10521 {
10522 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10523 } else {
10524 printf("Insufficient arguments]n\n");
10525 exit(-1);
10526 }
10527 val = strtok(NULL, ";");
10528 j++;
10529 }
10530 }
10531
10532 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10533 if (ret != RETURN_OK)
10534 {
10535 printf("wifi_setNeighborReports ret = %d", ret);
10536 exit(-1);
10537 }
10538 }
10539 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10540 {
10541 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10542 printf("%s.\n", buf);
10543 else
10544 printf("Error returned\n");
10545 }
10546 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10547 {
10548 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10549 printf("%s.\n", buf);
10550 else
10551 printf("Error returned\n");
10552 }
10553 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10554 {
10555 if (argc <= 2)
10556 {
10557 printf("Insufficient arguments\n");
10558 exit(-1);
10559 }
10560 char buf[64]= {'\0'};
10561 wifi_getRadioOperatingChannelBandwidth(index,buf);
10562 printf("Current bandwidth is %s \n",buf);
10563 return 0;
10564 }
10565 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
10566 {
10567 if (argc <= 5)
10568 {
10569 printf("Insufficient arguments\n");
10570 exit(-1);
10571 }
10572 UINT channel = atoi(argv[3]);
10573 UINT width = atoi(argv[4]);
10574 UINT beacon = atoi(argv[5]);
10575 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
10576 printf("Result = %d", ret);
10577 }
10578
10579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10580 return 0;
10581}
10582
10583#endif
10584
10585#ifdef WIFI_HAL_VERSION_3
10586
10587INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10588{
10589 // The only par-radio parameter is a channel number, however there's a 'dynamic' API
10590 // to change it ("wifi_pushRadioChannel2()") that is used instead.
10591 return RETURN_OK;
10592}
10593
10594INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
10595{
10596 INT ret;
10597 char band[128];
10598 ULONG channel;
10599 BOOL enabled;
10600 char buf[256];
10601
10602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10603 printf("Entering %s index = %d\n", __func__, (int)index);
10604
10605 ret = wifi_getRadioEnable(index, &enabled);
10606 if (ret != RETURN_OK)
10607 {
10608 printf("%s: cannot get enabled state for radio index %d\n", __func__,
10609 index);
10610 return RETURN_ERR;
10611 }
10612 operationParam->enable = enabled;
10613
10614 memset(band, 0, sizeof(band));
10615 ret = wifi_getRadioOperatingFrequencyBand(index, band);
10616 if (ret != RETURN_OK)
10617 {
10618 printf("%s: cannot get radio band for radio index %d\n", __func__, index);
10619 return RETURN_ERR;
10620 }
10621
10622 if (!strcmp(band, "2.4GHz"))
10623 {
10624 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
10625 operationParam->variant = WIFI_80211_VARIANT_N;
10626 }
10627 else if (!strcmp(band, "5GHz"))
10628 {
10629 operationParam->band = WIFI_FREQUENCY_5_BAND;
10630 operationParam->variant = WIFI_80211_VARIANT_AC;
10631 }
10632 else
10633 {
10634 printf("%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
10635 band);
10636 }
10637
10638 memset(buf, 0, sizeof(buf));
10639 ret = wifi_getRadioOperatingChannelBandwidth(index, buf); // XXX: handle errors
10640 // XXX: only handle 20/40/80 modes for now
10641 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
10642 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
10643 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
10644 else
10645 {
10646 printf("%s: Unknown HT mode: '%s'\n", __func__, buf);
10647 operationParam->channelWidth = 0;
10648 }
10649
10650 ret = wifi_getRadioChannel(index, &channel);
10651 if (ret != RETURN_OK)
10652 {
10653 printf("%s: Failed to get channel number for radio index %d\n", __func__, index);
10654 channel = 0;
10655 }
10656 operationParam->channel = channel;
10657 operationParam->csa_beacon_count = 15; // XXX: hardcoded for now
10658
10659 operationParam->countryCode = wifi_countrycode_US; // XXX: hardcoded for now
10660
10661 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10662 return RETURN_OK;
10663}
10664
10665static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
10666{
10667 if (radioIndex != 0 && radioIndex != 1)
10668 {
10669 printf("%s: Wrong radio index (%d)\n", __func__, index);
10670 return -1;
10671 }
10672
10673 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
10674 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
10675
10676 return (arrayIndex * 2) + radioIndex;
10677}
10678
10679INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10680{
10681 INT ret;
10682 int i;
10683 BOOL enabled = false;
10684 char buf[256];
10685 wifi_secur_list *secur_item;
10686 int vap_index;
10687 INT mode;
10688 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
10689
10690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10691 printf("Entering %s index = %d\n", __func__, (int)index);
10692
10693 map->vap_array[index].radio_index = index;
10694 for (i = 0; i < 5; i++)
10695 {
10696 vap_index = array_index_to_vap_index(index, i);
10697 if (vap_index < 0)
10698 {
10699 return RETURN_ERR;
10700 }
10701
10702 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
10703
10704 map->vap_array[i].vap_index = vap_index;
10705
10706 memset(buf, 0, sizeof(buf));
10707 wifi_getApName(vap_index, buf); // XXX: error handling
10708 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
10709
10710 ret = wifi_getSSIDEnable(vap_index, &enabled);
10711 if (ret != RETURN_OK)
10712 {
10713 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
10714 return RETURN_ERR;
10715 }
10716 map->vap_array[i].u.bss_info.enabled = enabled;
10717
10718 memset(buf, 0, sizeof(buf));
10719 wifi_getBaseBSSID(vap_index, buf);
10720 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10721 &map->vap_array[i].u.bss_info.bssid[0],
10722 &map->vap_array[i].u.bss_info.bssid[1],
10723 &map->vap_array[i].u.bss_info.bssid[2],
10724 &map->vap_array[i].u.bss_info.bssid[3],
10725 &map->vap_array[i].u.bss_info.bssid[4],
10726 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
10727
10728 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
10729 map->vap_array[i].u.bss_info.showSsid = enabled;
10730
10731 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
10732 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
10733 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
10734
10735 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
10736 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
10737
10738 memset(buf, 0, sizeof(buf));
10739 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
10740 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
10741
10742 wifi_getApSecurityModeEnabled(vap_index, buf);
10743
10744 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
10745 {
10746 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
10747 return RETURN_ERR;
10748 }
10749 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
10750
10751 memset(buf, 0, sizeof(buf));
10752 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
10753 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);
10754
10755 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
10756 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
10757
10758 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
10759 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
10760
10761 wifi_getApIsolationEnable(vap_index, &enabled);
10762 map->vap_array[i].u.bss_info.isolation = enabled;
10763 }
10764 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10765 return RETURN_OK;
10766}
10767
10768INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
10769{
10770 unsigned int i;
10771 wifi_vap_info_t *vap_info = NULL;
10772 int acl_mode;
10773 char *sec_str = NULL;
10774
10775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10776 printf("Entering %s index = %d\n", __func__, (int)index);
10777 for (i = 0; i < map->num_vaps; i++)
10778 {
10779 vap_info = &map->vap_array[i];
10780 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
10781
10782 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
10783 else
10784 {
10785 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
10786 else acl_mode = 1;
10787 }
10788 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
10789 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
10790 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
10791
10792 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
10793 if (sec_str)
10794 {
10795 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
10796 }
10797 else
10798 {
10799 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
10800 }
10801
10802 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
10803 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
10804
10805 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
10806 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
10807
10808 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
10809
10810 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
10811 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
10812 }
10813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10814 return RETURN_OK;
10815}
10816
10817int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
10818{
10819 char *token, *next;
10820 const char s[2] = ",";
10821 int count =0;
10822
10823 /* get the first token */
10824 token = strtok_r(pchannels, s, &next);
10825
10826 /* walk through other tokens */
10827 while( token != NULL && count < MAX_CHANNELS) {
10828 chlistptr->channels_list[count++] = atoi(token);
10829 token = strtok_r(NULL, s, &next);
10830 }
10831
10832 return count;
10833}
10834
10835static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
10836{
10837 INT status;
10838 wifi_channels_list_t *chlistp;
10839 CHAR output_string[64];
10840 CHAR pchannels[128];
10841
10842 if(rcap == NULL)
10843 {
10844 return RETURN_ERR;
10845 }
10846
10847 rcap->numSupportedFreqBand = 1;
10848 if (1 == radioIndex)
10849 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
10850 else
10851 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
10852
10853
10854 chlistp = &(rcap->channel_list[0]);
10855 memset(pchannels, 0, sizeof(pchannels));
10856
10857 /* possible number of radio channels */
10858 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
10859 {
10860 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
10861 }
10862 /* Number of channels and list*/
10863 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
10864
10865 /* autoChannelSupported */
10866 /* always ON with wifi_getRadioAutoChannelSupported */
10867 rcap->autoChannelSupported = TRUE;
10868
10869 /* DCSSupported */
10870 /* always ON with wifi_getRadioDCSSupported */
10871 rcap->DCSSupported = TRUE;
10872
10873 /* zeroDFSSupported - TBD */
10874 rcap->zeroDFSSupported = FALSE;
10875
10876 /* Supported Country List*/
10877 memset(output_string, 0, sizeof(output_string));
10878 status = wifi_getRadioCountryCode(radioIndex, output_string);
10879 if( status != 0 ) {
10880 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
10881 return RETURN_ERR;
10882 } else {
10883 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
10884 }
10885 if(!strcmp(output_string,"US")){
10886 rcap->countrySupported[0] = wifi_countrycode_US;
10887 rcap->countrySupported[1] = wifi_countrycode_CA;
10888 } else if (!strcmp(output_string,"CA")) {
10889 rcap->countrySupported[0] = wifi_countrycode_CA;
10890 rcap->countrySupported[1] = wifi_countrycode_US;
10891 } else {
10892 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
10893 }
10894
10895 rcap->numcountrySupported = 2;
10896
10897 /* csi */
10898 rcap->csi.maxDevices = 8;
10899 rcap->csi.soudingFrameSupported = TRUE;
10900
10901 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
10902
10903 /* channelWidth - all supported bandwidths */
10904 int i=0;
10905 rcap->channelWidth[i] = 0;
10906 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
10907 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
10908 WIFI_CHANNELBANDWIDTH_40MHZ);
10909
10910 }
10911 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
10912 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
10913 WIFI_CHANNELBANDWIDTH_40MHZ |
10914 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
10915 }
10916
10917
10918 /* mode - all supported variants */
10919 // rcap->mode[i] = WIFI_80211_VARIANT_H;
10920 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
10921 rcap->mode[i] = (WIFI_80211_VARIANT_N);
10922 }
10923 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
10924 rcap->mode[i] = ( WIFI_80211_VARIANT_AC );
10925 }
10926 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
10927 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
10928
10929 /* supportedBitRate - all supported bitrates */
10930 rcap->supportedBitRate[i] = 0;
10931 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
10932 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
10933 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
10934 }
10935 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND )) {
10936 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
10937 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
10938 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
10939 }
10940
10941
10942 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
10943 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
10944 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
10945 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
10946 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
10947 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
10948 rcap->cipherSupported = 0;
10949 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
10950 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
10951
10952 return RETURN_OK;
10953}
10954
10955INT wifi_getHalCapability(wifi_hal_capability_t *cap)
10956{
10957 INT status, radioIndex;
10958 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
10959 int iter = 0;
10960 unsigned int j;
10961 wifi_interface_name_idex_map_t *iface_info;
10962
10963 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10964
10965 memset(cap, 0, sizeof(wifi_hal_capability_t));
10966
10967 /* version */
10968 cap->version.major = WIFI_HAL_MAJOR_VERSION;
10969 cap->version.minor = WIFI_HAL_MINOR_VERSION;
10970
10971 /* number of radios platform property */
10972 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
10973 _syscmd(cmd, output, sizeof(output));
10974 cap->wifi_prop.numRadios = atoi(output);
10975
10976 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
10977 {
10978 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
10979 if (status != 0) {
10980 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
10981 return RETURN_ERR;
10982 }
10983
10984 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
10985 {
10986 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
10987 {
10988 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
10989 return RETURN_ERR;
10990 }
10991 iface_info = &cap->wifi_prop.interface_map[iter];
10992 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
10993 iface_info->rdk_radio_index = radioIndex;
10994 memset(output, 0, sizeof(output));
10995 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
10996 {
10997 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
10998 }
10999 // TODO: bridge name
11000 // TODO: vlan id
11001 // TODO: primary
11002 iface_info->index = array_index_to_vap_index(radioIndex, j);
11003 memset(output, 0, sizeof(output));
11004 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11005 {
11006 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11007 }
11008 iter++;
11009 }
11010 }
11011
11012 cap->BandSteeringSupported = FALSE;
11013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11014 return RETURN_OK;
11015}
11016
11017INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11018{
11019 //TODO
11020 return RETURN_OK;
11021}
11022
11023INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11024{
11025 //TODO
11026 return RETURN_OK;
11027}
11028
11029#endif /* WIFI_HAL_VERSION_3 */
11030
11031#ifdef WIFI_HAL_VERSION_3_PHASE2
11032INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
11033{
11034 return RETURN_OK;
11035}
11036#else
11037INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
11038{
11039 char cmd[128];
11040 BOOL status = false;
11041
11042 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
11043 return RETURN_ERR;
11044
11045 output_buf[0] = '\0';
11046
11047 wifi_getApEnable(ap_index,&status);
11048 if (!status)
11049 return RETURN_OK;
11050
11051 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
11052 _syscmd(cmd, output_buf, output_buf_size);
11053
11054 return RETURN_OK;
11055}
11056#endif
developer2f513ab2022-09-13 14:26:06 +080011057
11058INT wifi_getProxyArp(INT apIndex, BOOL *enable)
11059{
11060 char output[16]={'\0'};
11061 char config_file[MAX_BUF_SIZE] = {0};
11062
11063 if (!enable)
11064 return RETURN_ERR;
11065
11066 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
11067 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
11068
11069 if (strlen(output) == 0)
11070 *enable = FALSE;
11071 else if (strncmp(output, "1", 1) == 0)
11072 *enable = TRUE;
11073 else
11074 *enable = FALSE;
11075
11076 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
11077 return RETURN_OK;
11078}
developer2d9c30f2022-09-13 15:06:14 +080011079
11080INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
11081{
11082 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
11083 return RETURN_ERR;
11084 *output_enable=TRUE;
11085 return RETURN_OK;
11086}