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