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