DPP: Dynamic Controller initiated connection on Relay

Accept an incoming TCP connection from a Controller in a Relay that is
configured with dpp_relay_port even if that Controller is not configured
with a dpp_controller parameter. This allows more dynamic Controller
initiated operations, e.g., when using mDNS to discover a Relay.

This type of a dynamic Controller entry will not be used for exchanges
that are initiated by an Enrollee (i.e., based on a DPP Public Action
frame received by the Relay).

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-07-23 13:41:36 +03:00 committed by Jouni Malinen
parent d2388bcca5
commit ca682f80a9
4 changed files with 110 additions and 32 deletions

View file

@ -3353,6 +3353,7 @@ static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
struct dpp_relay_config config;
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;
@ -3366,7 +3367,8 @@ static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
if (hapd->conf->dpp_relay_port)
dpp_relay_listen(hapd->iface->interfaces->dpp,
hapd->conf->dpp_relay_port);
hapd->conf->dpp_relay_port,
&config);
#endif /* CONFIG_DPP2 */
return 0;

View file

@ -749,7 +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);
int dpp_relay_listen(struct dpp_global *dpp, int port);
int dpp_relay_listen(struct dpp_global *dpp, int port,
struct dpp_relay_config *config);
void dpp_relay_stop_listen(struct dpp_global *dpp);
int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
const u8 *buf, size_t len, unsigned int freq,

View file

@ -19,9 +19,16 @@ struct dpp_global {
struct dl_list configurator; /* struct dpp_configurator */
#ifdef CONFIG_DPP2
struct dl_list controllers; /* struct dpp_relay_controller */
struct dpp_relay_controller *tmp_controller;
struct dpp_controller *controller;
struct dl_list tcp_init; /* struct dpp_connection */
int relay_sock;
void *relay_msg_ctx;
void *relay_cb_ctx;
void (*relay_tx)(void *ctx, const u8 *addr, unsigned int freq,
const u8 *msg, size_t len);
void (*relay_gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token,
int prot, struct wpabuf *buf);
void *cb_ctx;
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);

View file

@ -211,6 +211,11 @@ dpp_relay_controller_get_addr(struct dpp_global *dpp,
return ctrl;
}
if (dpp->tmp_controller &&
dpp->tmp_controller->ipaddr.af == AF_INET &&
addr->sin_addr.s_addr == dpp->tmp_controller->ipaddr.u.v4.s_addr)
return dpp->tmp_controller;
return NULL;
}
@ -548,6 +553,31 @@ static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
}
static struct dpp_connection *
dpp_relay_match_ctrl(struct dpp_relay_controller *ctrl, const u8 *src,
unsigned int freq, u8 type)
{
struct dpp_connection *conn;
dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
return conn;
if ((type == DPP_PA_PKEX_EXCHANGE_RESP ||
type == DPP_PA_AUTHENTICATION_RESP) &&
conn->freq == 0 &&
is_broadcast_ether_addr(conn->mac_addr)) {
wpa_printf(MSG_DEBUG,
"DPP: Associate this peer to the new Controller initiated connection");
os_memcpy(conn->mac_addr, src, ETH_ALEN);
conn->freq = freq;
return conn;
}
}
return NULL;
}
int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
const u8 *buf, size_t len, unsigned int freq,
const u8 *i_bootstrap, const u8 *r_bootstrap,
@ -566,24 +596,16 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
type != DPP_PA_RECONFIG_ANNOUNCEMENT) {
dl_list_for_each(ctrl, &dpp->controllers,
struct dpp_relay_controller, list) {
dl_list_for_each(conn, &ctrl->conn,
struct dpp_connection, list) {
if (os_memcmp(src, conn->mac_addr,
ETH_ALEN) == 0)
return dpp_relay_tx(conn, hdr, buf, len);
if ((type == DPP_PA_PKEX_EXCHANGE_RESP ||
type == DPP_PA_AUTHENTICATION_RESP) &&
conn->freq == 0 &&
is_broadcast_ether_addr(conn->mac_addr)) {
wpa_printf(MSG_DEBUG,
"DPP: Associate this peer to the new Controller initiated connection");
os_memcpy(conn->mac_addr, src,
ETH_ALEN);
conn->freq = freq;
return dpp_relay_tx(conn, hdr, buf,
len);
}
}
conn = dpp_relay_match_ctrl(ctrl, src, freq, type);
if (conn)
return dpp_relay_tx(conn, hdr, buf, len);
}
if (dpp->tmp_controller) {
conn = dpp_relay_match_ctrl(dpp->tmp_controller, src,
freq, type);
if (conn)
return dpp_relay_tx(conn, hdr, buf, len);
}
}
@ -619,11 +641,25 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
}
static struct dpp_connection *
dpp_relay_find_conn(struct dpp_relay_controller *ctrl, const u8 *src)
{
struct dpp_connection *conn;
dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
return conn;
}
return NULL;
}
int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
size_t data_len)
{
struct dpp_relay_controller *ctrl;
struct dpp_connection *conn, *found = NULL;
struct dpp_connection *conn = NULL;
struct wpabuf *msg;
/* Check if there is a successfully completed authentication for this
@ -631,19 +667,15 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
*/
dl_list_for_each(ctrl, &dpp->controllers,
struct dpp_relay_controller, list) {
if (found)
conn = dpp_relay_find_conn(ctrl, src);
if (conn)
break;
dl_list_for_each(conn, &ctrl->conn,
struct dpp_connection, list) {
if (os_memcmp(src, conn->mac_addr,
ETH_ALEN) == 0) {
found = conn;
break;
}
}
}
if (!found)
if (!conn && dpp->tmp_controller)
conn = dpp_relay_find_conn(dpp->tmp_controller, src);
if (!conn)
return -1;
msg = wpabuf_alloc(4 + 1 + data_len);
@ -2326,6 +2358,11 @@ void dpp_relay_flush_controllers(struct dpp_global *dpp)
dl_list_del(&ctrl->list);
dpp_relay_controller_free(ctrl);
}
if (dpp->tmp_controller) {
dpp_relay_controller_free(dpp->tmp_controller);
dpp->tmp_controller = NULL;
}
}
@ -2351,6 +2388,32 @@ static void dpp_relay_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
ctrl = dpp_relay_controller_get_addr(dpp, &addr);
if (!ctrl && dpp->tmp_controller &&
dl_list_len(&dpp->tmp_controller->conn)) {
char txt[100];
wpa_printf(MSG_DEBUG,
"DPP: Remove a temporaty Controller entry for %s",
hostapd_ip_txt(&dpp->tmp_controller->ipaddr,
txt, sizeof(txt)));
dpp_relay_controller_free(dpp->tmp_controller);
dpp->tmp_controller = NULL;
}
if (!ctrl && !dpp->tmp_controller) {
wpa_printf(MSG_DEBUG, "DPP: Add a temporary Controller entry");
ctrl = os_zalloc(sizeof(*ctrl));
if (!ctrl)
goto fail;
dl_list_init(&ctrl->conn);
ctrl->global = dpp;
ctrl->ipaddr.af = AF_INET;
ctrl->ipaddr.u.v4.s_addr = addr.sin_addr.s_addr;
ctrl->msg_ctx = dpp->relay_msg_ctx;
ctrl->cb_ctx = dpp->relay_cb_ctx;
ctrl->tx = dpp->relay_tx;
ctrl->gas_resp_tx = dpp->relay_gas_resp_tx;
dpp->tmp_controller = ctrl;
}
if (!ctrl) {
wpa_printf(MSG_DEBUG,
"DPP: No Controller found for that address");
@ -2396,7 +2459,8 @@ fail:
}
int dpp_relay_listen(struct dpp_global *dpp, int port)
int dpp_relay_listen(struct dpp_global *dpp, int port,
struct dpp_relay_config *config)
{
int s;
int on = 1;
@ -2451,6 +2515,10 @@ int dpp_relay_listen(struct dpp_global *dpp, int port)
}
dpp->relay_sock = s;
dpp->relay_msg_ctx = config->msg_ctx;
dpp->relay_cb_ctx = config->cb_ctx;
dpp->relay_tx = config->tx;
dpp->relay_gas_resp_tx = config->gas_resp_tx;
wpa_printf(MSG_DEBUG, "DPP: Relay started on TCP port %d", port);
return 0;
}