DPP: Allow Relay connections to Controllers to be added and removed

The new control interface commands "DPP_RELAY_ADD_CONTROLLER <IP addr>
<PK hash>" and "DPP_RELAY_REMOVE_CONTROLLER <IP addr>" can now be used
to dynamically add and remove connections to Controllers for the cases
where the connection is initialized through a DPP Public Action frame
(i.e., Controller as the Responder).

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-07-23 17:41:00 +03:00 committed by Jouni Malinen
parent 808834b18b
commit bfe3cfc382
5 changed files with 101 additions and 0 deletions

View file

@ -3673,6 +3673,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
reply_len = -1;
} else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) {
hostapd_dpp_chirp_stop(hapd);
} else if (os_strncmp(buf, "DPP_RELAY_ADD_CONTROLLER ", 25) == 0) {
if (hostapd_dpp_add_controller(hapd, buf + 25) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "DPP_RELAY_REMOVE_CONTROLLER ", 28) == 0) {
hostapd_dpp_remove_controller(hapd, buf + 28);
#endif /* CONFIG_DPP2 */
#ifdef CONFIG_DPP3
} else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) {

View file

@ -21,6 +21,7 @@
#include "gas_query_ap.h"
#include "gas_serv.h"
#include "wpa_auth.h"
#include "beacon.h"
#include "dpp_hostapd.h"
@ -3375,6 +3376,65 @@ static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
}
#ifdef CONFIG_DPP2
int hostapd_dpp_add_controller(struct hostapd_data *hapd, const char *cmd)
{
struct dpp_relay_config config;
struct hostapd_ip_addr addr;
u8 pkhash[SHA256_MAC_LEN];
char *pos, *tmp;
int ret = -1;
bool prev_state, new_state;
struct dpp_global *dpp = hapd->iface->interfaces->dpp;
tmp = os_strdup(cmd);
if (!tmp)
goto fail;
pos = os_strchr(tmp, ' ');
if (!pos)
goto fail;
pos++;
if (hostapd_parse_ip_addr(tmp, &addr) < 0 ||
hexstr2bin(pos, pkhash, SHA256_MAC_LEN) < 0)
goto fail;
os_memset(&config, 0, sizeof(config));
config.msg_ctx = hapd->msg_ctx;
config.cb_ctx = hapd;
config.tx = hostapd_dpp_relay_tx;
config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
config.ipaddr = &addr;
config.pkhash = pkhash;
prev_state = dpp_relay_controller_available(dpp);
ret = dpp_relay_add_controller(dpp, &config);
new_state = dpp_relay_controller_available(dpp);
if (new_state != prev_state)
ieee802_11_update_beacons(hapd->iface);
fail:
os_free(tmp);
return ret;
}
void hostapd_dpp_remove_controller(struct hostapd_data *hapd, const char *cmd)
{
struct hostapd_ip_addr addr;
bool prev_state, new_state;
struct dpp_global *dpp = hapd->iface->interfaces->dpp;
if (hostapd_parse_ip_addr(cmd, &addr) < 0)
return;
prev_state = dpp_relay_controller_available(dpp);
dpp_relay_remove_controller(dpp, &addr);
new_state = dpp_relay_controller_available(dpp);
if (new_state != prev_state)
ieee802_11_update_beacons(hapd->iface);
}
#endif /* CONFIG_DPP2 */
int hostapd_dpp_init(struct hostapd_data *hapd)
{
hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;

View file

@ -48,5 +48,7 @@ void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi);
int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_push_button_stop(struct hostapd_data *hapd);
bool hostapd_dpp_configurator_connectivity(struct hostapd_data *hapd);
int hostapd_dpp_add_controller(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_remove_controller(struct hostapd_data *hapd, const char *cmd);
#endif /* DPP_HOSTAPD_H */

View file

@ -749,6 +749,8 @@ struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp,
const u8 *kid);
int dpp_relay_add_controller(struct dpp_global *dpp,
struct dpp_relay_config *config);
void dpp_relay_remove_controller(struct dpp_global *dpp,
const struct hostapd_ip_addr *addr);
int dpp_relay_listen(struct dpp_global *dpp, int port,
struct dpp_relay_config *config);
void dpp_relay_stop_listen(struct dpp_global *dpp);

View file

@ -139,6 +139,7 @@ int dpp_relay_add_controller(struct dpp_global *dpp,
struct dpp_relay_config *config)
{
struct dpp_relay_controller *ctrl;
char txt[100];
if (!dpp)
return -1;
@ -154,6 +155,8 @@ int dpp_relay_add_controller(struct dpp_global *dpp,
ctrl->cb_ctx = config->cb_ctx;
ctrl->tx = config->tx;
ctrl->gas_resp_tx = config->gas_resp_tx;
wpa_printf(MSG_DEBUG, "DPP: Add Relay connection to Controller %s",
hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
dl_list_add(&dpp->controllers, &ctrl->list);
return 0;
}
@ -2344,6 +2347,10 @@ void dpp_tcp_init_flush(struct dpp_global *dpp)
static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
{
struct dpp_connection *conn, *tmp;
char txt[100];
wpa_printf(MSG_DEBUG, "DPP: Remove Relay connection to Controller %s",
hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
list)
@ -2372,6 +2379,31 @@ void dpp_relay_flush_controllers(struct dpp_global *dpp)
}
void dpp_relay_remove_controller(struct dpp_global *dpp,
const struct hostapd_ip_addr *addr)
{
struct dpp_relay_controller *ctrl;
if (!dpp)
return;
dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
list) {
if (hostapd_ip_equal(&ctrl->ipaddr, addr)) {
dl_list_del(&ctrl->list);
dpp_relay_controller_free(ctrl);
return;
}
}
if (dpp->tmp_controller &&
hostapd_ip_equal(&dpp->tmp_controller->ipaddr, addr)) {
dpp_relay_controller_free(dpp->tmp_controller);
dpp->tmp_controller = NULL;
}
}
static void dpp_relay_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
{
struct dpp_global *dpp = eloop_ctx;