aboutsummaryrefslogtreecommitdiff
path: root/src/common/dpp_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/dpp_tcp.c')
-rw-r--r--src/common/dpp_tcp.c477
1 files changed, 443 insertions, 34 deletions
diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c
index e88c6de6..d226a8a8 100644
--- a/src/common/dpp_tcp.c
+++ b/src/common/dpp_tcp.c
@@ -48,6 +48,9 @@ struct dpp_connection {
unsigned int gas_comeback_in_progress:1;
u8 gas_dialog_token;
char *name;
+ char *mud_url;
+ char *extra_conf_req_name;
+ char *extra_conf_req_value;
enum dpp_netrole netrole;
};
@@ -89,6 +92,9 @@ static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
static void dpp_controller_auth_success(struct dpp_connection *conn,
int initiator);
static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx);
+#ifdef CONFIG_DPP3
+static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx);
+#endif /* CONFIG_DPP3 */
static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx);
static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -107,11 +113,17 @@ static void dpp_connection_free(struct dpp_connection *conn)
eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL);
eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
+#ifdef CONFIG_DPP3
+ eloop_cancel_timeout(dpp_tcp_build_new_key, conn, NULL);
+#endif /* CONFIG_DPP3 */
wpabuf_free(conn->msg);
wpabuf_free(conn->msg_out);
dpp_auth_deinit(conn->auth);
dpp_pkex_free(conn->pkex);
os_free(conn->name);
+ os_free(conn->mud_url);
+ os_free(conn->extra_conf_req_name);
+ os_free(conn->extra_conf_req_value);
os_free(conn);
}
@@ -127,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;
@@ -142,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;
}
@@ -183,6 +198,31 @@ dpp_relay_controller_get_ctx(struct dpp_global *dpp, void *cb_ctx)
}
+static struct dpp_relay_controller *
+dpp_relay_controller_get_addr(struct dpp_global *dpp,
+ const struct sockaddr_in *addr)
+{
+ struct dpp_relay_controller *ctrl;
+
+ if (!dpp)
+ return NULL;
+
+ dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
+ list) {
+ if (ctrl->ipaddr.af == AF_INET &&
+ addr->sin_addr.s_addr == ctrl->ipaddr.u.v4.s_addr)
+ 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;
+}
+
+
static void dpp_controller_gas_done(struct dpp_connection *conn)
{
struct dpp_authentication *auth = conn->auth;
@@ -193,6 +233,14 @@ static void dpp_controller_gas_done(struct dpp_connection *conn)
return;
}
+#ifdef CONFIG_DPP3
+ if (auth->waiting_new_key) {
+ wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
+ conn->on_tcp_tx_complete_gas_done = 0;
+ return;
+ }
+#endif /* CONFIG_DPP3 */
+
if (auth->peer_version >= 2 &&
auth->conf_resp_status == DPP_STATUS_OK) {
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
@@ -200,7 +248,8 @@ static void dpp_controller_gas_done(struct dpp_connection *conn)
return;
}
- wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
+ wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
+ auth->conf_resp_status);
dpp_connection_remove(conn);
}
@@ -298,8 +347,10 @@ static void dpp_controller_start_gas_client(struct dpp_connection *conn)
const char *dpp_name;
dpp_name = conn->name ? conn->name : "Test";
- buf = dpp_build_conf_req_helper(auth, dpp_name, conn->netrole, NULL,
- NULL);
+ buf = dpp_build_conf_req_helper(auth, dpp_name, conn->netrole,
+ conn->mud_url, NULL,
+ conn->extra_conf_req_name,
+ conn->extra_conf_req_value);
if (!buf) {
wpa_printf(MSG_DEBUG,
"DPP: No configuration request data available");
@@ -320,8 +371,7 @@ static void dpp_controller_auth_success(struct dpp_connection *conn,
return;
wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
- wpa_msg(conn->msg_ctx, MSG_INFO,
- DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
+ dpp_notify_auth_success(auth, initiator);
#ifdef CONFIG_TESTING_OPTIONS
if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
wpa_printf(MSG_INFO,
@@ -506,6 +556,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,
@@ -524,12 +599,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);
- }
+ 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);
}
}
@@ -548,6 +627,17 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
if (!ctrl)
return -1;
+ if (type == DPP_PA_PRESENCE_ANNOUNCEMENT ||
+ type == DPP_PA_RECONFIG_ANNOUNCEMENT) {
+ conn = dpp_relay_match_ctrl(ctrl, src, freq, type);
+ if (conn &&
+ (!conn->auth || conn->auth->waiting_auth_resp)) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Use existing TCP connection to Controller since no Auth Resp seen on it yet");
+ return dpp_relay_tx(conn, hdr, buf, len);
+ }
+ }
+
wpa_printf(MSG_DEBUG,
"DPP: Authentication Request for a configured Controller");
conn = dpp_relay_new_conn(ctrl, src, freq);
@@ -565,11 +655,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
@@ -577,19 +681,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);
@@ -608,6 +708,12 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
}
+bool dpp_relay_controller_available(struct dpp_global *dpp)
+{
+ return dpp && dl_list_len(&dpp->controllers) > 0;
+}
+
+
static void dpp_controller_free(struct dpp_controller *ctrl)
{
struct dpp_connection *conn, *tmp;
@@ -785,8 +891,9 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
status = dpp_conf_result_rx(auth, hdr, buf, len);
if (status == DPP_STATUS_OK && auth->send_conn_status) {
- wpa_msg(msg_ctx, MSG_INFO,
- DPP_EVENT_CONF_SENT "wait_conn_status=1");
+ wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
+ "wait_conn_status=1 conf_resp_status=%d",
+ auth->conf_resp_status);
wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
auth->waiting_conn_status_result = 1;
eloop_cancel_timeout(
@@ -798,7 +905,8 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
return 0;
}
if (status == DPP_STATUS_OK)
- wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
+ wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
+ "conf_resp_status=%d", auth->conf_resp_status);
else
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
return -1; /* to remove the completed connection */
@@ -847,12 +955,6 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn,
struct dpp_authentication *auth;
struct dpp_global *dpp = conn->ctrl->global;
- if (conn->auth) {
- wpa_printf(MSG_DEBUG,
- "DPP: Ignore Presence Announcement during ongoing Authentication");
- return -1;
- }
-
wpa_printf(MSG_DEBUG, "DPP: Presence Announcement");
r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
@@ -871,6 +973,12 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn,
return -1;
}
+ if (conn->auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore Presence Announcement during ongoing Authentication");
+ return 0;
+ }
+
auth = dpp_auth_init(dpp, conn->msg_ctx, peer_bi, NULL,
DPP_CAPAB_CONFIGURATOR, -1, NULL, 0);
if (!auth)
@@ -999,10 +1107,11 @@ static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
return 0;
}
- conn->pkex = dpp_pkex_rx_exchange_req(conn->ctrl->global, ctrl->pkex_bi,
+ conn->pkex = dpp_pkex_rx_exchange_req(conn->msg_ctx, ctrl->pkex_bi,
NULL, NULL,
ctrl->pkex_identifier,
ctrl->pkex_code,
+ os_strlen(ctrl->pkex_code),
buf, len, true);
if (!conn->pkex) {
wpa_printf(MSG_DEBUG,
@@ -1293,6 +1402,8 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
return -1;
}
+ wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX);
+
pos = msg;
end = msg + len;
@@ -1440,6 +1551,21 @@ static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx)
}
+#ifdef CONFIG_DPP3
+static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx)
+{
+ struct dpp_connection *conn = eloop_ctx;
+ struct dpp_authentication *auth = conn->auth;
+
+ if (!auth || !auth->waiting_new_key)
+ return;
+
+ wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
+ dpp_controller_start_gas_client(conn);
+}
+#endif /* CONFIG_DPP3 */
+
+
static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
{
struct dpp_authentication *auth = conn->auth;
@@ -1460,6 +1586,14 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL);
return 0;
}
+#ifdef CONFIG_DPP3
+ if (res == -3) {
+ wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
+ eloop_register_timeout(0, 0, dpp_tcp_build_new_key, conn,
+ NULL);
+ return 0;
+ }
+#endif /* CONFIG_DPP3 */
if (res < 0) {
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
return -1;
@@ -1874,7 +2008,10 @@ static int dpp_tcp_auth_start(struct dpp_connection *conn,
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,
+ enum dpp_netrole netrole, const char *mud_url,
+ const char *extra_conf_req_name,
+ const char *extra_conf_req_value,
+ void *msg_ctx, void *cb_ctx,
int (*process_conf_obj)(void *ctx,
struct dpp_authentication *auth),
bool (*tcp_msg_sent)(void *ctx,
@@ -1904,6 +2041,12 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
conn->process_conf_obj = process_conf_obj;
conn->tcp_msg_sent = tcp_msg_sent;
conn->name = os_strdup(name ? name : "Test");
+ if (mud_url)
+ conn->mud_url = os_strdup(mud_url);
+ if (extra_conf_req_name)
+ conn->extra_conf_req_name = os_strdup(extra_conf_req_name);
+ if (extra_conf_req_value)
+ conn->extra_conf_req_value = os_strdup(extra_conf_req_value);
conn->netrole = netrole;
conn->global = dpp;
conn->auth = auth;
@@ -1950,7 +2093,9 @@ fail:
int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
struct dpp_authentication *auth, const char *name,
- enum dpp_netrole netrole,
+ enum dpp_netrole netrole, const char *mud_url,
+ const char *extra_conf_req_name,
+ const char *extra_conf_req_value,
int (*process_conf_obj)(void *ctx,
struct dpp_authentication *auth),
bool (*tcp_msg_sent)(void *ctx,
@@ -1964,6 +2109,13 @@ int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
conn->tcp_msg_sent = tcp_msg_sent;
os_free(conn->name);
conn->name = os_strdup(name ? name : "Test");
+ os_free(conn->mud_url);
+ conn->mud_url = mud_url ? os_strdup(mud_url) : NULL;
+ os_free(conn->extra_conf_req_name);
+ conn->extra_conf_req_name = extra_conf_req_name ?
+ os_strdup(extra_conf_req_name) : NULL;
+ conn->extra_conf_req_value = extra_conf_req_value ?
+ os_strdup(extra_conf_req_value) : NULL;
conn->netrole = netrole;
conn->auth = auth;
@@ -2047,6 +2199,29 @@ fail:
}
+int dpp_controller_set_params(struct dpp_global *dpp,
+ const char *configurator_params)
+{
+
+ if (!dpp || !dpp->controller)
+ return -1;
+
+ if (configurator_params) {
+ char *val = os_strdup(configurator_params);
+
+ if (!val)
+ return -1;
+ os_free(dpp->controller->configurator_params);
+ dpp->controller->configurator_params = val;
+ } else {
+ os_free(dpp->controller->configurator_params);
+ dpp->controller->configurator_params = NULL;
+ }
+
+ return 0;
+}
+
+
void dpp_controller_stop(struct dpp_global *dpp)
{
if (dpp) {
@@ -2143,6 +2318,35 @@ void dpp_controller_pkex_add(struct dpp_global *dpp,
}
+bool dpp_controller_is_own_pkex_req(struct dpp_global *dpp,
+ const u8 *buf, size_t len)
+{
+ struct dpp_connection *conn;
+ const u8 *attr_key = NULL;
+ u16 attr_key_len = 0;
+
+ dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+ if (!conn->pkex || !conn->pkex->enc_key)
+ continue;
+
+ if (!attr_key) {
+ attr_key = dpp_get_attr(buf, len,
+ DPP_ATTR_ENCRYPTED_KEY,
+ &attr_key_len);
+ if (!attr_key)
+ return false;
+ }
+
+ if (attr_key_len == wpabuf_len(conn->pkex->enc_key) &&
+ os_memcmp(attr_key, wpabuf_head(conn->pkex->enc_key),
+ attr_key_len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+
void dpp_tcp_init_flush(struct dpp_global *dpp)
{
struct dpp_connection *conn, *tmp;
@@ -2156,6 +2360,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)
@@ -2176,6 +2384,204 @@ 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;
+ }
+}
+
+
+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;
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ int fd;
+ struct dpp_relay_controller *ctrl;
+ struct dpp_connection *conn = NULL;
+
+ wpa_printf(MSG_DEBUG, "DPP: New TCP connection (Relay)");
+
+ fd = accept(dpp->relay_sock, (struct sockaddr *) &addr, &addr_len);
+ if (fd < 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Failed to accept new connection: %s",
+ strerror(errno));
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
+ 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");
+ goto fail;
+ }
+
+ if (dl_list_len(&ctrl->conn) >= 15) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
+ goto fail;
+ }
+
+ conn = os_zalloc(sizeof(*conn));
+ if (!conn)
+ goto fail;
+
+ conn->global = ctrl->global;
+ conn->relay = ctrl;
+ conn->msg_ctx = ctrl->msg_ctx;
+ conn->cb_ctx = ctrl->global->cb_ctx;
+ os_memset(conn->mac_addr, 0xff, ETH_ALEN);
+ conn->sock = fd;
+
+ if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
+ dpp_controller_rx, conn, NULL) < 0)
+ goto fail;
+ conn->read_eloop = 1;
+
+ /* TODO: eloop timeout to expire connections that do not complete in
+ * reasonable time */
+ dl_list_add(&ctrl->conn, &conn->list);
+ return;
+
+fail:
+ close(fd);
+ os_free(conn);
+}
+
+
+int dpp_relay_listen(struct dpp_global *dpp, int port,
+ struct dpp_relay_config *config)
+{
+ int s;
+ int on = 1;
+ struct sockaddr_in sin;
+
+ if (dpp->relay_sock >= 0) {
+ wpa_printf(MSG_INFO, "DPP: %s(%d) - relay port already opened",
+ __func__, port);
+ return -1;
+ }
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ wpa_printf(MSG_INFO,
+ "DPP: socket(SOCK_STREAM) failed: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: setsockopt(SO_REUSEADDR) failed: %s",
+ strerror(errno));
+ /* try to continue anyway */
+ }
+
+ if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) {
+ wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
+ strerror(errno));
+ close(s);
+ return -1;
+ }
+
+ /* TODO: IPv6 */
+ os_memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_port = htons(port);
+ if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+ wpa_printf(MSG_INFO,
+ "DPP: Failed to bind Relay TCP port: %s",
+ strerror(errno));
+ close(s);
+ return -1;
+ }
+ if (listen(s, 10 /* max backlog */) < 0 ||
+ fcntl(s, F_SETFL, O_NONBLOCK) < 0 ||
+ eloop_register_sock(s, EVENT_TYPE_READ, dpp_relay_tcp_cb, dpp,
+ NULL)) {
+ close(s);
+ return -1;
+ }
+
+ 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;
+}
+
+
+void dpp_relay_stop_listen(struct dpp_global *dpp)
+{
+ if (!dpp || dpp->relay_sock < 0)
+ return;
+ eloop_unregister_sock(dpp->relay_sock, EVENT_TYPE_READ);
+ close(dpp->relay_sock);
+ dpp->relay_sock = -1;
}
@@ -2183,6 +2589,9 @@ bool dpp_tcp_conn_status_requested(struct dpp_global *dpp)
{
struct dpp_connection *conn;
+ if (!dpp)
+ return false;
+
dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
if (conn->auth && conn->auth->conn_status_requested)
return true;