diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 6239bebe5..96a13fb6f 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -2,6 +2,7 @@ * hostapd / DPP integration * Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2018-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -340,7 +341,7 @@ static int hostapd_dpp_pkex_done(void *ctx, void *conn, return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth, hapd->conf->dpp_name, DPP_NETROLE_AP, - hostapd_dpp_process_conf_obj); + hostapd_dpp_process_conf_obj, NULL); } #endif /* CONFIG_DPP2 */ @@ -922,7 +923,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) return dpp_tcp_init(hapd->iface->interfaces->dpp, auth, &ipaddr, tcp_port, hapd->conf->dpp_name, DPP_NETROLE_AP, hapd->msg_ctx, hapd, - hostapd_dpp_process_conf_obj); + hostapd_dpp_process_conf_obj, NULL); #endif /* CONFIG_DPP2 */ hapd->dpp_auth = auth; diff --git a/src/common/dpp.c b/src/common/dpp.c index ac6eae4c8..77964f264 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -2,6 +2,7 @@ * DPP functionality shared between hostapd and wpa_supplicant * Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2018-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. diff --git a/src/common/dpp.h b/src/common/dpp.h index ca488f391..83f3d94af 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -2,6 +2,7 @@ * DPP functionality shared between hostapd and wpa_supplicant * Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2018-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -402,6 +403,7 @@ struct dpp_controller_config { void *msg_ctx; void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); }; #ifdef CONFIG_TESTING_OPTIONS @@ -703,12 +705,21 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const char *name, enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx, int (*process_conf_obj)(void *ctx, - struct dpp_authentication *auth)); + struct dpp_authentication *auth), + bool (*tcp_msg_sent)(void *ctx, + struct dpp_authentication *auth)); int dpp_tcp_auth(struct dpp_global *dpp, void *_conn, struct dpp_authentication *auth, const char *name, enum dpp_netrole netrole, int (*process_conf_obj)(void *ctx, - struct dpp_authentication *auth)); + struct dpp_authentication *auth), + bool (*tcp_msg_sent)(void *ctx, + struct dpp_authentication *auth)); +bool dpp_tcp_conn_status_requested(struct dpp_global *dpp); +void dpp_tcp_send_conn_status(struct dpp_global *dpp, + enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list); struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index c00b1ee41..0f31ae56a 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -2,6 +2,7 @@ * DPP module internal definitions * Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2018-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -22,6 +23,7 @@ struct dpp_global { struct dl_list tcp_init; /* struct dpp_connection */ void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); #endif /* CONFIG_DPP2 */ }; diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 1a8a7c7d5..14ff2d903 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -1,6 +1,7 @@ /* * DPP over TCP * Copyright (c) 2019-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -30,6 +31,7 @@ struct dpp_connection { void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi); + bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); int sock; u8 mac_addr[ETH_ALEN]; unsigned int freq; @@ -79,6 +81,7 @@ struct dpp_controller { void *msg_ctx; void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); }; static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); @@ -245,6 +248,10 @@ static int dpp_tcp_send(struct dpp_connection *conn) dpp_controller_rx, conn, NULL) == 0) conn->read_eloop = 1; if (conn->on_tcp_tx_complete_remove) { + if (conn->auth && conn->auth->connect_on_tx_status && + conn->tcp_msg_sent && + conn->tcp_msg_sent(conn->cb_ctx, conn->auth)) + return 0; dpp_connection_remove(conn); } else if (conn->auth && (conn->ctrl || conn->auth->configurator) && conn->on_tcp_tx_complete_gas_done) { @@ -781,6 +788,7 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn, wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT "wait_conn_status=1"); wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); + auth->waiting_conn_status_result = 1; eloop_cancel_timeout( dpp_controller_conn_status_result_wait_timeout, conn, NULL); @@ -1697,6 +1705,7 @@ static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) conn->msg_ctx = ctrl->msg_ctx; conn->cb_ctx = ctrl->cb_ctx; conn->process_conf_obj = ctrl->process_conf_obj; + conn->tcp_msg_sent = ctrl->tcp_msg_sent; conn->sock = fd; conn->netrole = ctrl->netrole; @@ -1821,7 +1830,9 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, const char *name, enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx, int (*process_conf_obj)(void *ctx, - struct dpp_authentication *auth)) + struct dpp_authentication *auth), + bool (*tcp_msg_sent)(void *ctx, + struct dpp_authentication *auth)) { struct dpp_connection *conn; struct sockaddr_storage saddr; @@ -1845,6 +1856,7 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, conn->msg_ctx = msg_ctx; conn->cb_ctx = cb_ctx; conn->process_conf_obj = process_conf_obj; + conn->tcp_msg_sent = tcp_msg_sent; conn->name = os_strdup(name ? name : "Test"); conn->netrole = netrole; conn->global = dpp; @@ -1894,13 +1906,16 @@ int dpp_tcp_auth(struct dpp_global *dpp, void *_conn, struct dpp_authentication *auth, const char *name, enum dpp_netrole netrole, int (*process_conf_obj)(void *ctx, - struct dpp_authentication *auth)) + struct dpp_authentication *auth), + bool (*tcp_msg_sent)(void *ctx, + struct dpp_authentication *auth)) { struct dpp_connection *conn = _conn; /* Continue with Authentication exchange on an existing TCP connection. */ conn->process_conf_obj = process_conf_obj; + conn->tcp_msg_sent = tcp_msg_sent; os_free(conn->name); conn->name = os_strdup(name ? name : "Test"); conn->netrole = netrole; @@ -1939,6 +1954,7 @@ int dpp_controller_start(struct dpp_global *dpp, ctrl->msg_ctx = config->msg_ctx; ctrl->cb_ctx = config->cb_ctx; ctrl->process_conf_obj = config->process_conf_obj; + ctrl->tcp_msg_sent = config->tcp_msg_sent; ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); if (ctrl->sock < 0) @@ -2116,4 +2132,65 @@ void dpp_relay_flush_controllers(struct dpp_global *dpp) } } + +bool dpp_tcp_conn_status_requested(struct dpp_global *dpp) +{ + struct dpp_connection *conn; + + dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { + if (conn->auth && conn->auth->conn_status_requested) + return true; + } + + return false; +} + + +static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn, + enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list) +{ + struct dpp_authentication *auth = conn->auth; + int res; + struct wpabuf *msg; + + auth->conn_status_requested = 0; + + msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len, + channel_list); + if (!msg) { + dpp_connection_remove(conn); + return; + } + + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); + + if (res < 0) { + dpp_connection_remove(conn); + return; + } + + /* This exchange will be terminated in the TX status handler */ + conn->on_tcp_tx_complete_remove = 1; +} + + +void dpp_tcp_send_conn_status(struct dpp_global *dpp, + enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list) +{ + struct dpp_connection *conn; + + dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { + if (conn->auth && conn->auth->conn_status_requested) { + dpp_tcp_send_conn_status_msg(conn, result, ssid, + ssid_len, channel_list); + break; + } + } +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index b8c7a6712..acd8521c3 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2,6 +2,7 @@ * wpa_supplicant - DPP * Copyright (c) 2017, Qualcomm Atheros, Inc. * Copyright (c) 2018-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -53,6 +54,7 @@ static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s); static int wpas_dpp_process_conf_obj(void *ctx, struct dpp_authentication *auth); +static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth); #endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -295,7 +297,8 @@ static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx, struct dpp_authentication *auth = wpa_s->dpp_auth; enum dpp_status_error result; - if (!auth || !auth->conn_status_requested) + if ((!auth || !auth->conn_status_requested) && + !dpp_tcp_conn_status_requested(wpa_s->dpp)) return; wpa_printf(MSG_DEBUG, @@ -371,9 +374,10 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); - if (!auth || !auth->conn_status_requested) + if ((!auth || !auth->conn_status_requested) && + !dpp_tcp_conn_status_requested(wpa_s->dpp)) return; - auth->conn_status_requested = 0; + wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d", result); @@ -382,6 +386,19 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, channel_list = channel_list_buf; } + if (!auth || !auth->conn_status_requested) { + dpp_tcp_send_conn_status(wpa_s->dpp, result, + ssid ? ssid->ssid : + wpa_s->dpp_last_ssid, + ssid ? ssid->ssid_len : + wpa_s->dpp_last_ssid_len, + channel_list); + os_free(channel_list_buf); + return; + } + + auth->conn_status_requested = 0; + msg = dpp_build_conn_status_result(auth, result, ssid ? ssid->ssid : wpa_s->dpp_last_ssid, @@ -416,7 +433,8 @@ void wpas_dpp_connected(struct wpa_supplicant *wpa_s) { struct dpp_authentication *auth = wpa_s->dpp_auth; - if (auth && auth->conn_status_requested) + if ((auth && auth->conn_status_requested) || + dpp_tcp_conn_status_requested(wpa_s->dpp)) wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK); } @@ -874,7 +892,8 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) if (tcp) return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, wpa_s->conf->dpp_name, DPP_NETROLE_STA, - wpa_s, wpa_s, wpas_dpp_process_conf_obj); + wpa_s, wpa_s, wpas_dpp_process_conf_obj, + wpas_dpp_tcp_msg_sent); #endif /* CONFIG_DPP2 */ wpa_s->dpp_auth = auth; @@ -2028,6 +2047,34 @@ static int wpas_dpp_process_conf_obj(void *ctx, } +static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback"); + + if (auth->connect_on_tx_status) { + auth->connect_on_tx_status = 0; + wpa_printf(MSG_DEBUG, + "DPP: Try to connect after completed configuration result"); + wpas_dpp_try_to_connect(wpa_s); + if (auth->conn_status_requested) { + wpa_printf(MSG_DEBUG, + "DPP: Start 15 second timeout for reporting connection status result"); + eloop_cancel_timeout( + wpas_dpp_conn_status_result_timeout, + wpa_s, NULL); + eloop_register_timeout( + 15, 0, wpas_dpp_conn_status_result_timeout, + wpa_s, NULL); + return true; + } + } + + return false; +} + + static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) { struct wpa_supplicant *wpa_s = ctx; @@ -2617,7 +2664,8 @@ static int wpas_dpp_pkex_done(void *ctx, void *conn, } return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name, - DPP_NETROLE_STA, wpas_dpp_process_conf_obj); + DPP_NETROLE_STA, wpas_dpp_process_conf_obj, + wpas_dpp_tcp_msg_sent); } #endif /* CONFIG_DPP2 */ @@ -3641,6 +3689,7 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) config.msg_ctx = wpa_s; config.cb_ctx = wpa_s; config.process_conf_obj = wpas_dpp_process_conf_obj; + config.tcp_msg_sent = wpas_dpp_tcp_msg_sent; if (cmd) { pos = os_strstr(cmd, " tcp_port="); if (pos) {