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