Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions source/core/services/vap_svc.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ typedef enum {
connection_state_connected_wait_for_csa,
connection_state_connected_scan_list,
connection_state_disconnection_in_progress,
#ifdef UWM_EXT_WPS_SUPPORT
connection_state_set_wps_sta_mode_started,
connection_state_set_wps_sta_mode,
connection_state_set_wps_sta_mode_completed,
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to every #endif comment what if is it related to.

Suggested change
#endif
#endif /* UWM_EXT_WPS_SUPPORT */

} connection_state_t;

typedef struct scan_result {
Expand Down Expand Up @@ -190,6 +195,9 @@ extern int vap_svc_mesh_ext_update(vap_svc_t *svc, unsigned int radio_index,
wifi_vap_info_map_t *map, rdk_wifi_vap_info_t *rdk_vap_info);
extern int vap_svc_mesh_ext_event(vap_svc_t *svc, wifi_event_type_t type, wifi_event_subtype_t sub_type, vap_svc_event_t event, void *arg);
extern bool vap_svc_is_mesh_ext(unsigned int vap_index);
#ifdef UWM_EXT_WPS_SUPPORT
extern int vap_svc_mesh_ext_wps_credentials_received(vap_svc_t *svc, unsigned int vap_index);
#endif

vap_svc_t *get_svc_by_type(wifi_ctrl_t *ctrl, vap_svc_type_t type);
vap_svc_t *get_svc_by_vap_index(wifi_ctrl_t *ctrl, unsigned int vap_index);
Expand Down
144 changes: 143 additions & 1 deletion source/core/services/vap_svc_mesh_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,14 @@ static char *ext_conn_state_to_str(connection_state_t conn_state)
return "connected_scan_list";
case connection_state_disconnection_in_progress:
return "disconnection_in_progress";
#ifdef UWM_EXT_WPS_SUPPORT
case connection_state_set_wps_sta_mode_started:
return "set_wps_sta_mode_started";
case connection_state_set_wps_sta_mode:
return "set_wps_sta_mode";
case connection_state_set_wps_sta_mode_completed:
return "set_wps_sta_mode_completed";
#endif
default:
break;
}
Expand Down Expand Up @@ -1220,6 +1228,62 @@ int process_ext_connect_algorithm(vap_svc_t *svc)
case connection_state_disconnection_in_progress:
ext_try_disconnecting(svc);
break;

#ifdef UWM_EXT_WPS_SUPPORT
case connection_state_set_wps_sta_mode_started:
// Transition to set_wps_sta_mode state (do nothing, wait for state change)
ext_set_conn_state(ext, connection_state_set_wps_sta_mode, __func__, __LINE__);
break;

case connection_state_set_wps_sta_mode:
// Do nothing, wait for state change to set_wps_sta_mode_completed
wifi_util_dbg_print(WIFI_CTRL, "%s:%d: Waiting for WPS credentials in set_wps_sta_mode state\n", __func__, __LINE__);
break;

case connection_state_set_wps_sta_mode_completed:
// Deinit and reinit wpa_supplicant, then set state to disconnected_scan_list_none
{
unsigned int vap_index = 0;
unsigned char num_of_radios = getNumberRadios();
unsigned char radio_index = 0;
wifi_vap_info_map_t *vap_map = NULL;

// Find the STA VAP index
for (radio_index = 0; radio_index < num_of_radios; radio_index++) {
vap_map = (wifi_vap_info_map_t *)get_wifidb_vap_map(radio_index);
if (vap_map == NULL) {
continue;
}
unsigned int j;
for (j = 0; j < vap_map->num_vaps; j++) {
if (vap_svc_is_mesh_ext(vap_map->vap_array[j].vap_index) == true &&
vap_map->vap_array[j].vap_mode == wifi_vap_mode_sta) {
vap_index = vap_map->vap_array[j].vap_index;
break;
}
}
if (vap_index != 0) {
break;
}
}

if (vap_index != 0) {
wifi_util_info_print(WIFI_CTRL, "%s:%d: Deinitializing and reinitializing wpa_supplicant for vap_index %d\n",
Comment thread
bsomanath marked this conversation as resolved.
Comment on lines +1246 to +1271
Comment on lines +1246 to +1271
__func__, __LINE__, vap_index);
if (wifi_hal_sm_reinit(vap_index) == RETURN_OK) {
wifi_util_info_print(WIFI_CTRL, "%s:%d: Successfully reinitialized wpa_supplicant\n", __func__, __LINE__);
} else {
wifi_util_error_print(WIFI_CTRL, "%s:%d: Failed to reinitialize wpa_supplicant\n", __func__, __LINE__);
}
} else {
wifi_util_error_print(WIFI_CTRL, "%s:%d: Could not find STA VAP index\n", __func__, __LINE__);
}

ext_set_conn_state(ext, connection_state_disconnected_scan_list_none, __func__, __LINE__);
schedule_connect_sm(svc);
}
break;
#endif
}

return 0;
Expand Down Expand Up @@ -1271,6 +1335,12 @@ int vap_svc_mesh_ext_disconnect(vap_svc_t *svc)
int vap_svc_mesh_ext_start(vap_svc_t *svc, unsigned int radio_index, wifi_vap_info_map_t *map)
{
vap_svc_ext_t *ext = &svc->u.ext;
#ifdef UWM_EXT_WPS_SUPPORT
unsigned int wps_onboard_status = 0;
unsigned int j, vap_index = 0;
wifi_vap_info_map_t *vap_map = NULL;
wifi_radio_operationParam_t *radio_params = get_wifidb_radio_map(radio_index);
#endif

wifi_util_info_print(WIFI_CTRL, "%s:%d mesh service start\n", __func__, __LINE__);

Expand All @@ -1281,6 +1351,36 @@ int vap_svc_mesh_ext_start(vap_svc_t *svc, unsigned int radio_index, wifi_vap_in
return -1;
}

#ifdef UWM_EXT_WPS_SUPPORT
if(radio_params != NULL && is_radio_band_5G(radio_params->band)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it important that radio was 5G?

vap_map = (wifi_vap_info_map_t *)get_wifidb_vap_map(radio_index);
if (vap_map != NULL)
{
for (j = 0; j < vap_map->num_vaps; j++)
{
wifi_util_info_print(WIFI_CTRL, "%s:%d Vap_name: %s Mesh status: %d vap_mode: %d valid_bh: %d\n", __FUNCTION__, __LINE__,
vap_map->vap_array[j].vap_name, vap_svc_is_mesh_ext(vap_map->vap_array[j].vap_index), vap_map->vap_array[j].vap_mode,
vap_map->vap_array[j].u.sta_info.valid_bh_credentials);
if (vap_svc_is_mesh_ext(vap_map->vap_array[j].vap_index) == true &&
vap_map->vap_array[j].vap_mode == wifi_vap_mode_sta &&
vap_map->vap_array[j].u.sta_info.valid_bh_credentials == FALSE)
{
wps_onboard_status = 1;
vap_index = vap_map->vap_array[j].vap_index;
wifi_util_info_print(WIFI_CTRL, "%s:%d WPS Onboarding required for vap_index: %d\n", __FUNCTION__, __LINE__, vap_index);
break;
}
Comment thread
bsomanath marked this conversation as resolved.
}
}
if (wps_onboard_status) {
ext_set_conn_state(ext, connection_state_set_wps_sta_mode_started, __func__, __LINE__);
wifi_util_info_print(WIFI_CTRL, "%s:%d: WPS onboarding required - valid_bh_credentials not set for STA vap_index %d\n",
__FUNCTION__, __LINE__, vap_index);
schedule_connect_sm(svc);
}
Comment thread
bsomanath marked this conversation as resolved.
Comment on lines +1354 to +1380
}
#endif

/* create STA vap's and install acl filters */
if (!ext->is_vap_started[radio_index]) {
vap_svc_start(svc, radio_index);
Expand All @@ -1296,6 +1396,7 @@ int vap_svc_mesh_ext_start(vap_svc_t *svc, unsigned int radio_index, wifi_vap_in
memset(ext, 0, sizeof(vap_svc_ext_t));

ext_set_conn_state(ext, connection_state_disconnected_scan_list_none, __func__, __LINE__);

schedule_connect_sm(svc);
Comment thread
bsomanath marked this conversation as resolved.

Comment on lines 1354 to 1401
ext->is_started = true;
Expand Down Expand Up @@ -2282,7 +2383,11 @@ int process_ext_sta_conn_status(vap_svc_t *svc, void *arg)
__LINE__, ext_conn_state_to_str(ext->conn_state));
schedule_connect_sm(svc);
}
} else if((found_candidate == false) && (ext->conn_state != connection_state_connected)) {
} else if((found_candidate == false) && (ext->conn_state != connection_state_connected)
#ifdef UWM_EXT_WPS_SUPPORT
&& (ext->conn_state != connection_state_set_wps_sta_mode_completed)
#endif
) {
wifi_util_info_print(WIFI_CTRL, "%s:%d candidate null connection state: %s\r\n",
__func__, __LINE__, ext_conn_state_to_str(ext->conn_state));
if (ext->conn_state != connection_state_disconnected_scan_list_none) {
Expand Down Expand Up @@ -2328,6 +2433,43 @@ int process_ext_channel_change(vap_svc_t *svc, void *arg)
return 0;
}

#ifdef UWM_EXT_WPS_SUPPORT
/**
* @brief Handle WPS credentials received event for station interface
* @param svc VAP service pointer
* @param vap_index VAP index where WPS occurred
* @return 0 on success, -1 on failure
*/
int vap_svc_mesh_ext_wps_credentials_received(vap_svc_t *svc, unsigned int vap_index)
{
vap_svc_ext_t *ext = &svc->u.ext;

wifi_util_info_print(WIFI_CTRL, "%s:%d: WPS credentials received for vap_index %d\n",
__func__, __LINE__, vap_index);

/* Credentials are already updated in vap_info structure by wifi_hal_wps_event */
/* Just set the connection state to set_wps_sta_mode_completed */
if (ext->conn_state == connection_state_set_wps_sta_mode ||
ext->conn_state == connection_state_set_wps_sta_mode_started ||
ext->conn_state == connection_state_disconnected_scan_list_none) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ext->conn_state == connection_state_disconnected_scan_list_none) {
ext->conn_state == connection_state_disconnected_scan_list_none) {

wifi_util_info_print(WIFI_CTRL, "%s:%d: Setting state to set_wps_sta_mode_completed "
"(current state: %s)\n", __func__, __LINE__,
ext_conn_state_to_str(ext->conn_state));

ext_set_conn_state(ext, connection_state_set_wps_sta_mode_completed, __func__, __LINE__);

/* Schedule connect algorithm to process the state change */
schedule_connect_sm(svc);
} else {
wifi_util_dbg_print(WIFI_CTRL, "%s:%d: WPS credentials received but not in expected state "
"(current state: %s)\n", __func__, __LINE__,
ext_conn_state_to_str(ext->conn_state));
}

return 0;
}
#endif

int process_ext_hal_ind(vap_svc_t *svc, wifi_event_subtype_t sub_type, void *arg)
{
switch (sub_type) {
Expand Down
73 changes: 72 additions & 1 deletion source/core/services/vap_svc_private.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
#include <stdbool.h>
#include "stdlib.h"
#include <sys/time.h>
#include <string.h>
#include "vap_svc.h"
#include "wifi_ctrl.h"
#include "wifi_util.h"
#include "wifi_hal.h"

bool vap_svc_is_private(unsigned int vap_index)
{
Expand Down Expand Up @@ -92,7 +94,8 @@ int vap_svc_private_update(vap_svc_t *svc, unsigned int radio_index, wifi_vap_in
unsigned int i;
wifi_vap_info_map_t *p_tgt_vap_map = NULL;
int ret;

wifi_platform_property_t *wifi_prop = get_wifi_hal_cap_prop();

p_tgt_vap_map = (wifi_vap_info_map_t *) malloc( sizeof(wifi_vap_info_map_t) );
if (p_tgt_vap_map == NULL) {
wifi_util_error_print(WIFI_CTRL,"%s:%d Failed to allocate memory.\n", __FUNCTION__,__LINE__);
Expand All @@ -112,6 +115,38 @@ int vap_svc_private_update(vap_svc_t *svc, unsigned int radio_index, wifi_vap_in
wifi_util_error_print(WIFI_CTRL, "%s:%d configure_lnf_psk_radius_from_hotspot failed\n", __FUNCTION__, __LINE__);
Comment thread
bsomanath marked this conversation as resolved.
Comment thread
bsomanath marked this conversation as resolved.
return -1;
}

#if defined(_PLATFORM_BANANAPI_R4_) && defined(EM_WPS_FH_HACK)
{
int band;
wifi_vap_info_t *vap = &p_tgt_vap_map->vap_array[0];
unsigned int vap_index = map->vap_array[i].vap_index;

if (convert_radio_index_to_freq_band(wifi_prop, radio_index, &band) == RETURN_OK) {
/*
* Private SSID on 2.4/5 GHz with WPS: disable MLO/MLD and use WPA2-Personal + PSK.
* MLD left enabled while forcing WPA2 breaks hostapd / EasyMesh topology; WPS also
* expects classic WPA2-PSK on these bands.
*/
if (isVapPrivate(vap_index) && map->vap_array[i].u.bss_info.wps.enable &&
band != WIFI_FREQUENCY_6_BAND) {
vap->u.bss_info.mld_info.common_info.mld_enable = 0;
vap->u.bss_info.mld_info.common_info.mld_id = 255;
vap->u.bss_info.mld_info.common_info.mld_link_id = 255;
memset(vap->u.bss_info.mld_info.common_info.mld_addr, 0,
sizeof(vap->u.bss_info.mld_info.common_info.mld_addr));
vap->u.bss_info.mld_info.common_info.mld_apply = 1;

vap->u.bss_info.security.mode = wifi_security_mode_wpa2_personal;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why enforcing WPA2?

vap->u.bss_info.security.encr = wifi_encryption_aes;
vap->u.bss_info.security.mfp = wifi_mfp_cfg_optional;
vap->u.bss_info.security.wpa3_transition_disable = false;
vap->u.bss_info.security.u.key.type = wifi_security_key_type_psk;
}
}
}
#endif

#if defined(_WNXL11BWL_PRODUCT_REQ_)
if (rdk_vap_info[i].exists == false && isVapPrivate(map->vap_array[i].vap_index)) {
wifi_util_error_print(WIFI_CTRL,"%s:%d VAP_EXISTS_FALSE for vap_index=%d, setting to TRUE \n",__FUNCTION__,__LINE__,map->vap_array[i].vap_index);
Expand All @@ -132,6 +167,42 @@ int vap_svc_private_update(vap_svc_t *svc, unsigned int radio_index, wifi_vap_in
#endif /* !defined(_PP203X_PRODUCT_REQ_) && !defined(_GREXT02ACTS_PRODUCT_REQ_) */
p_tgt_vap_map->vap_array[0].u.bss_info.enabled &= rdk_vap_info[i].exists;

// If WPS is enabled on private VAP, copy mesh backhaul credentials into multi_ap_backhaul structure
if (map->vap_array[i].u.bss_info.wps.enable && isVapPrivate(map->vap_array[i].vap_index)) {
wifi_vap_name_t vap_names[MAX_NUM_RADIOS] = {0};
unsigned int num_vaps = get_list_of_mesh_backhaul(wifi_prop, MAX_NUM_RADIOS, vap_names);
wifi_vap_info_t *backhaul_vap_info = NULL;

if (num_vaps > 0) {
int backhaul_vap_index = convert_vap_name_to_index(wifi_prop, vap_names[0]);
if (backhaul_vap_index >= 0) {
backhaul_vap_info = get_wifidb_vap_parameters(backhaul_vap_index);
}
}
if (backhaul_vap_info != NULL &&
strlen((char *)backhaul_vap_info->u.bss_info.ssid) > 0 &&
strlen((char *)backhaul_vap_info->u.bss_info.security.u.key.key) > 0 &&
strcmp((char *)backhaul_vap_info->u.bss_info.security.u.key.key, INVALID_KEY) != 0) {
memset(p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_ssid, 0,
sizeof(p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_ssid));
strncpy((char *)p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_ssid,
(char *)backhaul_vap_info->u.bss_info.ssid,
sizeof(p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_ssid) - 1);

memset(p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_network_key, 0,
sizeof(p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_network_key));
strncpy((char *)p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_network_key,
(char *)backhaul_vap_info->u.bss_info.security.u.key.key,
sizeof(p_tgt_vap_map->vap_array[0].u.bss_info.multi_ap_backhaul_network_key) - 1);

wifi_util_info_print(WIFI_CTRL, "%s:%d Copied mesh backhaul credentials to multi_ap_backhaul for private VAP %d\n",
__FUNCTION__, __LINE__, map->vap_array[i].vap_index);
} else {
wifi_util_dbg_print(WIFI_CTRL, "%s:%d Mesh backhaul credentials not found or invalid, WPS enabled without backhaul for VAP %d\n",
__FUNCTION__, __LINE__, map->vap_array[i].vap_index);
}
}

ret = wifi_hal_createVAP(radio_index, p_tgt_vap_map);
if (ret != RETURN_OK) {
wifi_util_error_print(WIFI_CTRL,"%s: wifi vap create failure: radio_index:%d vap_index:%d\n",__FUNCTION__,
Expand Down
48 changes: 48 additions & 0 deletions source/core/wifi_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,49 @@ static int wps_event_callback(int apIndex, wifi_wps_ev_t event)
return RETURN_OK;
}

#ifdef UWM_EXT_WPS_SUPPORT
/**
* @brief WPS STA event callback - called when WPS credentials are received for station interface
* @param vap_index VAP index where WPS occurred
* @param event WPS event (2 = WPS_EV_SUCCESS)
* @return None
*/
static void wps_sta_event_callback(unsigned int vap_index, unsigned int event)
{
wifi_ctrl_t *ctrl = get_wifictrl_obj();
vap_svc_t *ext_svc = NULL;

wifi_util_info_print(WIFI_CTRL, "%s:%d: WPS STA event callback: vap_index=%d, event=%d\n",
__func__, __LINE__, vap_index, event);

/* Only handle WPS_EV_SUCCESS (value 2) */
if (event != 2) {
wifi_util_dbg_print(WIFI_CTRL, "%s:%d: Ignoring non-success WPS event %d\n",
__func__, __LINE__, event);
return;
Comment thread
bsomanath marked this conversation as resolved.
Comment on lines +1394 to +1401
}
Comment thread
bsomanath marked this conversation as resolved.
Comment on lines +1386 to +1402

if (ctrl == NULL) {
wifi_util_error_print(WIFI_CTRL, "%s:%d: ctrl is NULL\n",
__func__, __LINE__);
return;
}

/* Find the mesh extender service for this VAP using the existing API */
ext_svc = get_svc_by_vap_index(ctrl, vap_index);
if (ext_svc != NULL && ext_svc->type == vap_svc_type_mesh_ext) {
/* Found the service - call the WPS credentials handler */
wifi_util_info_print(WIFI_CTRL, "%s:%d: Calling vap_svc_mesh_ext_wps_credentials_received "
"for vap_index %d\n", __func__, __LINE__, vap_index);
vap_svc_mesh_ext_wps_credentials_received(ext_svc, vap_index);
} else {
Comment thread
bsomanath marked this conversation as resolved.
wifi_util_dbg_print(WIFI_CTRL, "%s:%d: Could not find mesh extender service for vap_index %d "
"(ext_svc=%p, type=%d)\n", __func__, __LINE__, vap_index, ext_svc,
ext_svc ? ext_svc->type : -1);
}
}
#endif

int init_wifi_ctrl(wifi_ctrl_t *ctrl)
{
unsigned int i;
Expand Down Expand Up @@ -1463,6 +1506,11 @@ int init_wifi_ctrl(wifi_ctrl_t *ctrl)

wifi_wpsEvent_callback_register(wps_event_callback);

#ifdef UWM_EXT_WPS_SUPPORT
/* Register WPS STA event callback for mesh extender WPS support */
wifi_wpsStaEvent_callback_register(wps_sta_event_callback);
#endif

ctrl->bus_events_subscribed = false;
ctrl->tunnel_events_subscribed = false;

Expand Down
Loading
Loading