blob: fc53b8a0b7ca3112e14696eccabe8d65777ea623 [file] [log] [blame]
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001/*
2 * DPP over TCP
3 * Copyright (c) 2019-2020, The Linux Foundation
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10#include <fcntl.h>
11
12#include "utils/common.h"
13#include "utils/ip_addr.h"
14#include "utils/eloop.h"
15#include "common/ieee802_11_common.h"
16#include "common/wpa_ctrl.h"
17#include "dpp.h"
18#include "dpp_i.h"
19
20#ifdef CONFIG_DPP2
21
22struct dpp_connection {
23 struct dl_list list;
24 struct dpp_controller *ctrl;
25 struct dpp_relay_controller *relay;
26 struct dpp_global *global;
27 struct dpp_authentication *auth;
28 int sock;
29 u8 mac_addr[ETH_ALEN];
30 unsigned int freq;
31 u8 msg_len[4];
32 size_t msg_len_octets;
33 struct wpabuf *msg;
34 struct wpabuf *msg_out;
35 size_t msg_out_pos;
36 unsigned int read_eloop:1;
37 unsigned int write_eloop:1;
38 unsigned int on_tcp_tx_complete_gas_done:1;
39 unsigned int on_tcp_tx_complete_remove:1;
40 unsigned int on_tcp_tx_complete_auth_ok:1;
41};
42
43/* Remote Controller */
44struct dpp_relay_controller {
45 struct dl_list list;
46 struct dpp_global *global;
47 u8 pkhash[SHA256_MAC_LEN];
48 struct hostapd_ip_addr ipaddr;
49 void *cb_ctx;
50 void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
51 size_t len);
52 void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token,
53 int prot, struct wpabuf *buf);
54 struct dl_list conn; /* struct dpp_connection */
55};
56
57/* Local Controller */
58struct dpp_controller {
59 struct dpp_global *global;
60 u8 allowed_roles;
61 int qr_mutual;
62 int sock;
63 struct dl_list conn; /* struct dpp_connection */
64 char *configurator_params;
65};
66
67static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
68static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
69static void dpp_controller_auth_success(struct dpp_connection *conn,
70 int initiator);
71
72
73static void dpp_connection_free(struct dpp_connection *conn)
74{
75 if (conn->sock >= 0) {
76 wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d",
77 conn->sock);
78 eloop_unregister_sock(conn->sock, EVENT_TYPE_READ);
79 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
80 close(conn->sock);
81 }
82 eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout,
83 conn, NULL);
84 wpabuf_free(conn->msg);
85 wpabuf_free(conn->msg_out);
86 dpp_auth_deinit(conn->auth);
87 os_free(conn);
88}
89
90
91static void dpp_connection_remove(struct dpp_connection *conn)
92{
93 dl_list_del(&conn->list);
94 dpp_connection_free(conn);
95}
96
97
98int dpp_relay_add_controller(struct dpp_global *dpp,
99 struct dpp_relay_config *config)
100{
101 struct dpp_relay_controller *ctrl;
102
103 if (!dpp)
104 return -1;
105
106 ctrl = os_zalloc(sizeof(*ctrl));
107 if (!ctrl)
108 return -1;
109 dl_list_init(&ctrl->conn);
110 ctrl->global = dpp;
111 os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr));
112 os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN);
113 ctrl->cb_ctx = config->cb_ctx;
114 ctrl->tx = config->tx;
115 ctrl->gas_resp_tx = config->gas_resp_tx;
116 dl_list_add(&dpp->controllers, &ctrl->list);
117 return 0;
118}
119
120
121static struct dpp_relay_controller *
122dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash)
123{
124 struct dpp_relay_controller *ctrl;
125
126 if (!dpp)
127 return NULL;
128
129 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
130 list) {
131 if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0)
132 return ctrl;
133 }
134
135 return NULL;
136}
137
138
139static void dpp_controller_gas_done(struct dpp_connection *conn)
140{
141 struct dpp_authentication *auth = conn->auth;
142 void *msg_ctx;
143
144 if (auth->peer_version >= 2 &&
145 auth->conf_resp_status == DPP_STATUS_OK) {
146 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
147 auth->waiting_conf_result = 1;
148 return;
149 }
150
151 if (conn->ctrl)
152 msg_ctx = conn->ctrl->global->msg_ctx;
153 else
154 msg_ctx = auth->msg_ctx;
155 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
156 dpp_connection_remove(conn);
157}
158
159
160static int dpp_tcp_send(struct dpp_connection *conn)
161{
162 int res;
163
164 if (!conn->msg_out) {
165 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
166 conn->write_eloop = 0;
167 return -1;
168 }
169 res = send(conn->sock,
170 wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos,
171 wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0);
172 if (res < 0) {
173 wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s",
174 strerror(errno));
175 dpp_connection_remove(conn);
176 return -1;
177 }
178
179 conn->msg_out_pos += res;
180 if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) {
181 wpa_printf(MSG_DEBUG,
182 "DPP: %u/%u bytes of message sent to Controller",
183 (unsigned int) conn->msg_out_pos,
184 (unsigned int) wpabuf_len(conn->msg_out));
185 if (!conn->write_eloop &&
186 eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
187 dpp_conn_tx_ready, conn, NULL) == 0)
188 conn->write_eloop = 1;
189 return 1;
190 }
191
192 wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP");
193 wpabuf_free(conn->msg_out);
194 conn->msg_out = NULL;
195 conn->msg_out_pos = 0;
196 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
197 conn->write_eloop = 0;
198 if (!conn->read_eloop &&
199 eloop_register_sock(conn->sock, EVENT_TYPE_READ,
200 dpp_controller_rx, conn, NULL) == 0)
201 conn->read_eloop = 1;
202 if (conn->on_tcp_tx_complete_remove) {
203 dpp_connection_remove(conn);
204 } else if (conn->auth && (conn->ctrl || conn->auth->configurator) &&
205 conn->on_tcp_tx_complete_gas_done) {
206 dpp_controller_gas_done(conn);
207 } else if (conn->on_tcp_tx_complete_auth_ok) {
208 conn->on_tcp_tx_complete_auth_ok = 0;
209 dpp_controller_auth_success(conn, 1);
210 }
211
212 return 0;
213}
214
215
216static int dpp_tcp_send_msg(struct dpp_connection *conn,
217 const struct wpabuf *msg)
218{
219 wpabuf_free(conn->msg_out);
220 conn->msg_out_pos = 0;
221 conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
222 if (!conn->msg_out)
223 return -1;
224 wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1);
225 wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1,
226 wpabuf_len(msg) - 1);
227
228 if (dpp_tcp_send(conn) == 1) {
229 if (!conn->write_eloop) {
230 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
231 dpp_conn_tx_ready,
232 conn, NULL) < 0)
233 return -1;
234 conn->write_eloop = 1;
235 }
236 }
237
238 return 0;
239}
240
241
242static void dpp_controller_start_gas_client(struct dpp_connection *conn)
243{
244 struct dpp_authentication *auth = conn->auth;
245 struct wpabuf *buf;
246 int netrole_ap = 0; /* TODO: make this configurable */
247
248 buf = dpp_build_conf_req_helper(auth, "Test", netrole_ap, NULL, NULL);
249 if (!buf) {
250 wpa_printf(MSG_DEBUG,
251 "DPP: No configuration request data available");
252 return;
253 }
254
255 dpp_tcp_send_msg(conn, buf);
256 wpabuf_free(buf);
257}
258
259
260static void dpp_controller_auth_success(struct dpp_connection *conn,
261 int initiator)
262{
263 struct dpp_authentication *auth = conn->auth;
264
265 if (!auth)
266 return;
267
268 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
269 wpa_msg(conn->global->msg_ctx, MSG_INFO,
270 DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
271#ifdef CONFIG_TESTING_OPTIONS
272 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
273 wpa_printf(MSG_INFO,
274 "DPP: TESTING - stop at Authentication Confirm");
275 if (auth->configurator) {
276 /* Prevent GAS response */
277 auth->auth_success = 0;
278 }
279 return;
280 }
281#endif /* CONFIG_TESTING_OPTIONS */
282
283 if (!auth->configurator)
284 dpp_controller_start_gas_client(conn);
285}
286
287
288static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
289{
290 struct dpp_connection *conn = eloop_ctx;
291
292 wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock);
293 dpp_tcp_send(conn);
294}
295
296
297static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen,
298 const struct hostapd_ip_addr *ipaddr,
299 int port)
300{
301 struct sockaddr_in *dst;
302#ifdef CONFIG_IPV6
303 struct sockaddr_in6 *dst6;
304#endif /* CONFIG_IPV6 */
305
306 switch (ipaddr->af) {
307 case AF_INET:
308 dst = (struct sockaddr_in *) addr;
309 os_memset(dst, 0, sizeof(*dst));
310 dst->sin_family = AF_INET;
311 dst->sin_addr.s_addr = ipaddr->u.v4.s_addr;
312 dst->sin_port = htons(port);
313 *addrlen = sizeof(*dst);
314 break;
315#ifdef CONFIG_IPV6
316 case AF_INET6:
317 dst6 = (struct sockaddr_in6 *) addr;
318 os_memset(dst6, 0, sizeof(*dst6));
319 dst6->sin6_family = AF_INET6;
320 os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6,
321 sizeof(struct in6_addr));
322 dst6->sin6_port = htons(port);
323 *addrlen = sizeof(*dst6);
324 break;
325#endif /* CONFIG_IPV6 */
326 default:
327 return -1;
328 }
329
330 return 0;
331}
332
333
334static struct dpp_connection *
335dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
336 unsigned int freq)
337{
338 struct dpp_connection *conn;
339 struct sockaddr_storage addr;
340 socklen_t addrlen;
341 char txt[100];
342
343 if (dl_list_len(&ctrl->conn) >= 15) {
344 wpa_printf(MSG_DEBUG,
345 "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
346 return NULL;
347 }
348
349 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen,
350 &ctrl->ipaddr, DPP_TCP_PORT) < 0)
351 return NULL;
352
353 conn = os_zalloc(sizeof(*conn));
354 if (!conn)
355 return NULL;
356
357 conn->global = ctrl->global;
358 conn->relay = ctrl;
359 os_memcpy(conn->mac_addr, src, ETH_ALEN);
360 conn->freq = freq;
361
362 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
363 if (conn->sock < 0)
364 goto fail;
365 wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s",
366 conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
367
368 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
369 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
370 strerror(errno));
371 goto fail;
372 }
373
374 if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) {
375 if (errno != EINPROGRESS) {
376 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
377 strerror(errno));
378 goto fail;
379 }
380
381 /*
382 * Continue connecting in the background; eloop will call us
383 * once the connection is ready (or failed).
384 */
385 }
386
387 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
388 dpp_conn_tx_ready, conn, NULL) < 0)
389 goto fail;
390 conn->write_eloop = 1;
391
392 /* TODO: eloop timeout to clear a connection if it does not complete
393 * properly */
394
395 dl_list_add(&ctrl->conn, &conn->list);
396 return conn;
397fail:
398 dpp_connection_free(conn);
399 return NULL;
400}
401
402
403static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len)
404{
405 struct wpabuf *msg;
406
407 msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len);
408 if (!msg)
409 return NULL;
410 wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len);
411 wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
412 wpabuf_put_data(msg, hdr, DPP_HDR_LEN);
413 wpabuf_put_data(msg, buf, len);
414 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
415 return msg;
416}
417
418
419static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
420 const u8 *buf, size_t len)
421{
422 u8 type = hdr[DPP_HDR_LEN - 1];
423
424 wpa_printf(MSG_DEBUG,
425 "DPP: Continue already established Relay/Controller connection for this session");
426 wpabuf_free(conn->msg_out);
427 conn->msg_out_pos = 0;
428 conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
429 if (!conn->msg_out) {
430 dpp_connection_remove(conn);
431 return -1;
432 }
433
434 /* TODO: for proto ver 1, need to do remove connection based on GAS Resp
435 * TX status */
436 if (type == DPP_PA_CONFIGURATION_RESULT)
437 conn->on_tcp_tx_complete_remove = 1;
438 dpp_tcp_send(conn);
439 return 0;
440}
441
442
443int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
444 const u8 *buf, size_t len, unsigned int freq,
445 const u8 *i_bootstrap, const u8 *r_bootstrap)
446{
447 struct dpp_relay_controller *ctrl;
448 struct dpp_connection *conn;
449 u8 type = hdr[DPP_HDR_LEN - 1];
450
451 /* Check if there is an already started session for this peer and if so,
452 * continue that session (send this over TCP) and return 0.
453 */
454 if (type != DPP_PA_PEER_DISCOVERY_REQ &&
455 type != DPP_PA_PEER_DISCOVERY_RESP &&
456 type != DPP_PA_PRESENCE_ANNOUNCEMENT &&
457 type != DPP_PA_RECONFIG_ANNOUNCEMENT) {
458 dl_list_for_each(ctrl, &dpp->controllers,
459 struct dpp_relay_controller, list) {
460 dl_list_for_each(conn, &ctrl->conn,
461 struct dpp_connection, list) {
462 if (os_memcmp(src, conn->mac_addr,
463 ETH_ALEN) == 0)
464 return dpp_relay_tx(conn, hdr, buf, len);
465 }
466 }
467 }
468
469 if (type == DPP_PA_PRESENCE_ANNOUNCEMENT ||
470 type == DPP_PA_RECONFIG_ANNOUNCEMENT) {
471 /* TODO: Could send this to all configured Controllers. For now,
472 * only the first Controller is supported. */
473 ctrl = dl_list_first(&dpp->controllers,
474 struct dpp_relay_controller, list);
475 } else {
476 if (!r_bootstrap)
477 return -1;
478 ctrl = dpp_relay_controller_get(dpp, r_bootstrap);
479 }
480 if (!ctrl)
481 return -1;
482
483 wpa_printf(MSG_DEBUG,
484 "DPP: Authentication Request for a configured Controller");
485 conn = dpp_relay_new_conn(ctrl, src, freq);
486 if (!conn)
487 return -1;
488
489 conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
490 if (!conn->msg_out) {
491 dpp_connection_remove(conn);
492 return -1;
493 }
494 /* Message will be sent in dpp_conn_tx_ready() */
495
496 return 0;
497}
498
499
500int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
501 size_t data_len)
502{
503 struct dpp_relay_controller *ctrl;
504 struct dpp_connection *conn, *found = NULL;
505 struct wpabuf *msg;
506
507 /* Check if there is a successfully completed authentication for this
508 * and if so, continue that session (send this over TCP) and return 0.
509 */
510 dl_list_for_each(ctrl, &dpp->controllers,
511 struct dpp_relay_controller, list) {
512 if (found)
513 break;
514 dl_list_for_each(conn, &ctrl->conn,
515 struct dpp_connection, list) {
516 if (os_memcmp(src, conn->mac_addr,
517 ETH_ALEN) == 0) {
518 found = conn;
519 break;
520 }
521 }
522 }
523
524 if (!found)
525 return -1;
526
527 msg = wpabuf_alloc(4 + 1 + data_len);
528 if (!msg)
529 return -1;
530 wpabuf_put_be32(msg, 1 + data_len);
531 wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ);
532 wpabuf_put_data(msg, data, data_len);
533 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
534
535 wpabuf_free(conn->msg_out);
536 conn->msg_out_pos = 0;
537 conn->msg_out = msg;
538 dpp_tcp_send(conn);
539 return 0;
540}
541
542
543static void dpp_controller_free(struct dpp_controller *ctrl)
544{
545 struct dpp_connection *conn, *tmp;
546
547 if (!ctrl)
548 return;
549
550 dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
551 list)
552 dpp_connection_remove(conn);
553
554 if (ctrl->sock >= 0) {
555 close(ctrl->sock);
556 eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
557 }
558 os_free(ctrl->configurator_params);
559 os_free(ctrl);
560}
561
562
563static int dpp_controller_rx_auth_req(struct dpp_connection *conn,
564 const u8 *hdr, const u8 *buf, size_t len)
565{
566 const u8 *r_bootstrap, *i_bootstrap;
567 u16 r_bootstrap_len, i_bootstrap_len;
568 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
569
570 if (!conn->ctrl)
571 return 0;
572
573 wpa_printf(MSG_DEBUG, "DPP: Authentication Request");
574
575 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
576 &r_bootstrap_len);
577 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
578 wpa_printf(MSG_INFO,
579 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
580 return -1;
581 }
582 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
583 r_bootstrap, r_bootstrap_len);
584
585 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
586 &i_bootstrap_len);
587 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
588 wpa_printf(MSG_INFO,
589 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
590 return -1;
591 }
592 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
593 i_bootstrap, i_bootstrap_len);
594
595 /* Try to find own and peer bootstrapping key matches based on the
596 * received hash values */
597 dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap,
598 &own_bi, &peer_bi);
599 if (!own_bi) {
600 wpa_printf(MSG_INFO,
601 "No matching own bootstrapping key found - ignore message");
602 return -1;
603 }
604
605 if (conn->auth) {
606 wpa_printf(MSG_INFO,
607 "Already in DPP authentication exchange - ignore new one");
608 return 0;
609 }
610
611 conn->auth = dpp_auth_req_rx(conn->ctrl->global,
612 conn->ctrl->global->msg_ctx,
613 conn->ctrl->allowed_roles,
614 conn->ctrl->qr_mutual,
615 peer_bi, own_bi, -1, hdr, buf, len);
616 if (!conn->auth) {
617 wpa_printf(MSG_DEBUG, "DPP: No response generated");
618 return -1;
619 }
620
621 if (dpp_set_configurator(conn->auth,
622 conn->ctrl->configurator_params) < 0) {
623 dpp_connection_remove(conn);
624 return -1;
625 }
626
627 return dpp_tcp_send_msg(conn, conn->auth->resp_msg);
628}
629
630
631static int dpp_controller_rx_auth_resp(struct dpp_connection *conn,
632 const u8 *hdr, const u8 *buf, size_t len)
633{
634 struct dpp_authentication *auth = conn->auth;
635 struct wpabuf *msg;
636 int res;
637
638 if (!auth)
639 return -1;
640
641 wpa_printf(MSG_DEBUG, "DPP: Authentication Response");
642
643 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
644 if (!msg) {
645 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
646 wpa_printf(MSG_DEBUG,
647 "DPP: Start wait for full response");
648 return -1;
649 }
650 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
651 dpp_connection_remove(conn);
652 return -1;
653 }
654
655 conn->on_tcp_tx_complete_auth_ok = 1;
656 res = dpp_tcp_send_msg(conn, msg);
657 wpabuf_free(msg);
658 return res;
659}
660
661
662static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
663 const u8 *hdr, const u8 *buf, size_t len)
664{
665 struct dpp_authentication *auth = conn->auth;
666
667 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation");
668
669 if (!auth) {
670 wpa_printf(MSG_DEBUG,
671 "DPP: No DPP Authentication in progress - drop");
672 return -1;
673 }
674
675 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
676 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
677 return -1;
678 }
679
680 dpp_controller_auth_success(conn, 0);
681 return 0;
682}
683
684
685void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
686 void *timeout_ctx)
687{
688 struct dpp_connection *conn = eloop_ctx;
689
690 if (!conn->auth->waiting_conf_result)
691 return;
692
693 wpa_printf(MSG_DEBUG,
694 "DPP: Timeout while waiting for Connection Status Result");
695 wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
696 DPP_EVENT_CONN_STATUS_RESULT "timeout");
697 dpp_connection_remove(conn);
698}
699
700
701static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
702 const u8 *hdr, const u8 *buf,
703 size_t len)
704{
705 struct dpp_authentication *auth = conn->auth;
706 enum dpp_status_error status;
707 void *msg_ctx;
708
709 if (!conn->ctrl && (!auth || !auth->configurator))
710 return 0;
711
712 wpa_printf(MSG_DEBUG, "DPP: Configuration Result");
713
714 if (!auth || !auth->waiting_conf_result) {
715 wpa_printf(MSG_DEBUG,
716 "DPP: No DPP Configuration waiting for result - drop");
717 return -1;
718 }
719 if (conn->ctrl)
720 msg_ctx = conn->ctrl->global->msg_ctx;
721 else
722 msg_ctx = auth->msg_ctx;
723
724 status = dpp_conf_result_rx(auth, hdr, buf, len);
725 if (status == DPP_STATUS_OK && auth->send_conn_status) {
726 wpa_msg(msg_ctx, MSG_INFO,
727 DPP_EVENT_CONF_SENT "wait_conn_status=1");
728 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
729 eloop_cancel_timeout(
730 dpp_controller_conn_status_result_wait_timeout,
731 conn, NULL);
732 eloop_register_timeout(
733 16, 0, dpp_controller_conn_status_result_wait_timeout,
734 conn, NULL);
735 return 0;
736 }
737 if (status == DPP_STATUS_OK)
738 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
739 else
740 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
741 return -1; /* to remove the completed connection */
742}
743
744
745static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn,
746 const u8 *hdr, const u8 *buf,
747 size_t len)
748{
749 struct dpp_authentication *auth = conn->auth;
750 enum dpp_status_error status;
751 u8 ssid[SSID_MAX_LEN];
752 size_t ssid_len = 0;
753 char *channel_list = NULL;
754
755 if (!conn->ctrl)
756 return 0;
757
758 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
759
760 if (!auth || !auth->waiting_conn_status_result) {
761 wpa_printf(MSG_DEBUG,
762 "DPP: No DPP Configuration waiting for connection status result - drop");
763 return -1;
764 }
765
766 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
767 ssid, &ssid_len, &channel_list);
768 wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
769 DPP_EVENT_CONN_STATUS_RESULT
770 "result=%d ssid=%s channel_list=%s",
771 status, wpa_ssid_txt(ssid, ssid_len),
772 channel_list ? channel_list : "N/A");
773 os_free(channel_list);
774 return -1; /* to remove the completed connection */
775}
776
777
778static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn,
779 const u8 *hdr, const u8 *buf,
780 size_t len)
781{
782 const u8 *r_bootstrap;
783 u16 r_bootstrap_len;
784 struct dpp_bootstrap_info *peer_bi;
785 struct dpp_authentication *auth;
786 struct dpp_global *dpp = conn->ctrl->global;
787
788 if (conn->auth) {
789 wpa_printf(MSG_DEBUG,
790 "DPP: Ignore Presence Announcement during ongoing Authentication");
791 return -1;
792 }
793
794 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement");
795
796 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
797 &r_bootstrap_len);
798 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
799 wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
800 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
801 return -1;
802 }
803 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
804 r_bootstrap, r_bootstrap_len);
805 peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap);
806 if (!peer_bi) {
807 wpa_printf(MSG_DEBUG,
808 "DPP: No matching bootstrapping information found");
809 return -1;
810 }
811
812 auth = dpp_auth_init(dpp, dpp->msg_ctx, peer_bi, NULL,
813 DPP_CAPAB_CONFIGURATOR, -1, NULL, 0);
814 if (!auth)
815 return -1;
816 if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
817 dpp_auth_deinit(auth);
818 dpp_connection_remove(conn);
819 return -1;
820 }
821
822 conn->auth = auth;
823 return dpp_tcp_send_msg(conn, conn->auth->req_msg);
824}
825
826
827static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn,
828 const u8 *hdr, const u8 *buf,
829 size_t len)
830{
831 const u8 *csign_hash;
832 u16 csign_hash_len;
833 struct dpp_configurator *conf;
834 struct dpp_global *dpp = conn->ctrl->global;
835 struct dpp_authentication *auth;
836
837 if (conn->auth) {
838 wpa_printf(MSG_DEBUG,
839 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
840 return -1;
841 }
842
843 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement");
844
845 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
846 &csign_hash_len);
847 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
848 wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
849 "Missing or invalid required Configurator C-sign key Hash attribute");
850 return -1;
851 }
852 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
853 csign_hash, csign_hash_len);
854 conf = dpp_configurator_find_kid(dpp, csign_hash);
855 if (!conf) {
856 wpa_printf(MSG_DEBUG,
857 "DPP: No matching Configurator information found");
858 return -1;
859 }
860
861 auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0);
862 if (!auth)
863 return -1;
864 if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
865 dpp_auth_deinit(auth);
866 return -1;
867 }
868
869 conn->auth = auth;
870 return dpp_tcp_send_msg(conn, auth->reconfig_req_msg);
871}
872
873
874static int dpp_controller_rx_reconfig_auth_resp(struct dpp_connection *conn,
875 const u8 *hdr, const u8 *buf,
876 size_t len)
877{
878 struct dpp_authentication *auth = conn->auth;
879 struct wpabuf *conf;
880 int res;
881
882 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response");
883
884 if (!auth || !auth->reconfig || !auth->configurator) {
885 wpa_printf(MSG_DEBUG,
886 "DPP: No DPP Reconfig Authentication in progress - drop");
887 return -1;
888 }
889
890 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
891 if (!conf)
892 return -1;
893
894 res = dpp_tcp_send_msg(conn, conf);
895 wpabuf_free(conf);
896 return res;
897}
898
899
900static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
901 size_t len)
902{
903 const u8 *pos, *end;
904 u8 type;
905
906 wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP");
907 pos = msg;
908 end = msg + len;
909
910 if (end - pos < DPP_HDR_LEN ||
911 WPA_GET_BE24(pos) != OUI_WFA ||
912 pos[3] != DPP_OUI_TYPE) {
913 wpa_printf(MSG_DEBUG, "DPP: Unrecognized header");
914 return -1;
915 }
916
917 if (pos[4] != 1) {
918 wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u",
919 pos[4]);
920 return -1;
921 }
922 type = pos[5];
923 wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type);
924 pos += DPP_HDR_LEN;
925
926 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes",
927 pos, end - pos);
928 if (dpp_check_attrs(pos, end - pos) < 0)
929 return -1;
930
931 if (conn->relay) {
932 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
933 conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr,
934 conn->freq, msg, len);
935 return 0;
936 }
937
938 switch (type) {
939 case DPP_PA_AUTHENTICATION_REQ:
940 return dpp_controller_rx_auth_req(conn, msg, pos, end - pos);
941 case DPP_PA_AUTHENTICATION_RESP:
942 return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos);
943 case DPP_PA_AUTHENTICATION_CONF:
944 return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
945 case DPP_PA_CONFIGURATION_RESULT:
946 return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
947 case DPP_PA_CONNECTION_STATUS_RESULT:
948 return dpp_controller_rx_conn_status_result(conn, msg, pos,
949 end - pos);
950 case DPP_PA_PRESENCE_ANNOUNCEMENT:
951 return dpp_controller_rx_presence_announcement(conn, msg, pos,
952 end - pos);
953 case DPP_PA_RECONFIG_ANNOUNCEMENT:
954 return dpp_controller_rx_reconfig_announcement(conn, msg, pos,
955 end - pos);
956 case DPP_PA_RECONFIG_AUTH_RESP:
957 return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos,
958 end - pos);
959 default:
960 /* TODO: missing messages types */
961 wpa_printf(MSG_DEBUG,
962 "DPP: Unsupported frame subtype %d", type);
963 return -1;
964 }
965}
966
967
968static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
969 size_t len)
970{
971 const u8 *pos, *end, *next;
972 u8 dialog_token;
973 const u8 *adv_proto;
974 u16 slen;
975 struct wpabuf *resp, *buf;
976 struct dpp_authentication *auth = conn->auth;
977
978 if (len < 1 + 2)
979 return -1;
980
981 wpa_printf(MSG_DEBUG,
982 "DPP: Received DPP Configuration Request over TCP");
983
984 if (!auth || (!conn->ctrl && !auth->configurator) ||
985 (!auth->auth_success && !auth->reconfig_success)) {
986 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
987 return -1;
988 }
989
990 pos = msg;
991 end = msg + len;
992
993 dialog_token = *pos++;
994 adv_proto = pos++;
995 slen = *pos++;
996 if (*adv_proto != WLAN_EID_ADV_PROTO ||
997 slen > end - pos || slen < 2)
998 return -1;
999
1000 next = pos + slen;
1001 pos++; /* skip QueryRespLenLimit and PAME-BI */
1002
1003 if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
1004 pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
1005 pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
1006 return -1;
1007
1008 pos = next;
1009 /* Query Request */
1010 if (end - pos < 2)
1011 return -1;
1012 slen = WPA_GET_LE16(pos);
1013 pos += 2;
1014 if (slen > end - pos)
1015 return -1;
1016
1017 resp = dpp_conf_req_rx(auth, pos, slen);
1018 if (!resp)
1019 return -1;
1020
1021 buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp));
1022 if (!buf) {
1023 wpabuf_free(resp);
1024 return -1;
1025 }
1026
1027 wpabuf_put_be32(buf, 18 + wpabuf_len(resp));
1028
1029 wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP);
1030 wpabuf_put_u8(buf, dialog_token);
1031 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
1032 wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */
1033
1034 dpp_write_adv_proto(buf);
1035 dpp_write_gas_query(buf, resp);
1036 wpabuf_free(resp);
1037
1038 /* Send Config Response over TCP; GAS fragmentation is taken care of by
1039 * the Relay */
1040 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
1041 wpabuf_free(conn->msg_out);
1042 conn->msg_out_pos = 0;
1043 conn->msg_out = buf;
1044 conn->on_tcp_tx_complete_gas_done = 1;
1045 dpp_tcp_send(conn);
1046 return 0;
1047}
1048
1049
1050static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
1051{
1052 struct dpp_authentication *auth = conn->auth;
1053 int res;
1054 struct wpabuf *msg;
1055 enum dpp_status_error status;
1056
1057 wpa_printf(MSG_DEBUG,
1058 "DPP: Configuration Response for local stack from TCP");
1059
1060 if (auth)
1061 res = dpp_conf_resp_rx(auth, resp);
1062 else
1063 res = -1;
1064 wpabuf_free(resp);
1065 if (res < 0) {
1066 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1067 return -1;
1068 }
1069
1070 if (conn->global->process_conf_obj)
1071 res = conn->global->process_conf_obj(conn->global->cb_ctx,
1072 auth);
1073 else
1074 res = 0;
1075
1076 if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK)
1077 return -1;
1078
1079 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1080 status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK;
1081 msg = dpp_build_conf_result(auth, status);
1082 if (!msg)
1083 return -1;
1084
1085 conn->on_tcp_tx_complete_remove = 1;
1086 res = dpp_tcp_send_msg(conn, msg);
1087 wpabuf_free(msg);
1088
1089 /* This exchange will be terminated in the TX status handler */
1090
1091 return res;
1092}
1093
1094
1095static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg,
1096 size_t len)
1097{
1098 struct wpabuf *buf;
1099 u8 dialog_token;
1100 const u8 *pos, *end, *next, *adv_proto;
1101 u16 status, slen;
1102
1103 if (len < 5 + 2)
1104 return -1;
1105
1106 wpa_printf(MSG_DEBUG,
1107 "DPP: Received DPP Configuration Response over TCP");
1108
1109 pos = msg;
1110 end = msg + len;
1111
1112 dialog_token = *pos++;
1113 status = WPA_GET_LE16(pos);
1114 if (status != WLAN_STATUS_SUCCESS) {
1115 wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status);
1116 return -1;
1117 }
1118 pos += 2;
1119 pos += 2; /* ignore GAS Comeback Delay */
1120
1121 adv_proto = pos++;
1122 slen = *pos++;
1123 if (*adv_proto != WLAN_EID_ADV_PROTO ||
1124 slen > end - pos || slen < 2)
1125 return -1;
1126
1127 next = pos + slen;
1128 pos++; /* skip QueryRespLenLimit and PAME-BI */
1129
1130 if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
1131 pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
1132 pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
1133 return -1;
1134
1135 pos = next;
1136 /* Query Response */
1137 if (end - pos < 2)
1138 return -1;
1139 slen = WPA_GET_LE16(pos);
1140 pos += 2;
1141 if (slen > end - pos)
1142 return -1;
1143
1144 buf = wpabuf_alloc(slen);
1145 if (!buf)
1146 return -1;
1147 wpabuf_put_data(buf, pos, slen);
1148
1149 if (!conn->relay &&
1150 (!conn->ctrl || (conn->ctrl->allowed_roles & DPP_CAPAB_ENROLLEE)))
1151 return dpp_tcp_rx_gas_resp(conn, buf);
1152
1153 if (!conn->relay) {
1154 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1155 wpabuf_free(buf);
1156 return -1;
1157 }
1158 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
1159 conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr,
1160 dialog_token, 0, buf);
1161
1162 return 0;
1163}
1164
1165
1166static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx)
1167{
1168 struct dpp_connection *conn = eloop_ctx;
1169 int res;
1170 const u8 *pos;
1171
1172 wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)",
1173 sd);
1174
1175 if (conn->msg_len_octets < 4) {
1176 u32 msglen;
1177
1178 res = recv(sd, &conn->msg_len[conn->msg_len_octets],
1179 4 - conn->msg_len_octets, 0);
1180 if (res < 0) {
1181 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s",
1182 strerror(errno));
1183 dpp_connection_remove(conn);
1184 return;
1185 }
1186 if (res == 0) {
1187 wpa_printf(MSG_DEBUG,
1188 "DPP: No more data available over TCP");
1189 dpp_connection_remove(conn);
1190 return;
1191 }
1192 wpa_printf(MSG_DEBUG,
1193 "DPP: Received %d/%d octet(s) of message length field",
1194 res, (int) (4 - conn->msg_len_octets));
1195 conn->msg_len_octets += res;
1196
1197 if (conn->msg_len_octets < 4) {
1198 wpa_printf(MSG_DEBUG,
1199 "DPP: Need %d more octets of message length field",
1200 (int) (4 - conn->msg_len_octets));
1201 return;
1202 }
1203
1204 msglen = WPA_GET_BE32(conn->msg_len);
1205 wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen);
1206 if (msglen > 65535) {
1207 wpa_printf(MSG_INFO, "DPP: Unexpectedly long message");
1208 dpp_connection_remove(conn);
1209 return;
1210 }
1211
1212 wpabuf_free(conn->msg);
1213 conn->msg = wpabuf_alloc(msglen);
1214 }
1215
1216 if (!conn->msg) {
1217 wpa_printf(MSG_DEBUG,
1218 "DPP: No buffer available for receiving the message");
1219 dpp_connection_remove(conn);
1220 return;
1221 }
1222
1223 wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload",
1224 (unsigned int) wpabuf_tailroom(conn->msg));
1225
1226 res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0);
1227 if (res < 0) {
1228 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno));
1229 dpp_connection_remove(conn);
1230 return;
1231 }
1232 if (res == 0) {
1233 wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP");
1234 dpp_connection_remove(conn);
1235 return;
1236 }
1237 wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res);
1238 wpabuf_put(conn->msg, res);
1239
1240 if (wpabuf_tailroom(conn->msg) > 0) {
1241 wpa_printf(MSG_DEBUG,
1242 "DPP: Need %u more octets of message payload",
1243 (unsigned int) wpabuf_tailroom(conn->msg));
1244 return;
1245 }
1246
1247 conn->msg_len_octets = 0;
1248 wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg);
1249 if (wpabuf_len(conn->msg) < 1) {
1250 dpp_connection_remove(conn);
1251 return;
1252 }
1253
1254 pos = wpabuf_head(conn->msg);
1255 switch (*pos) {
1256 case WLAN_PA_VENDOR_SPECIFIC:
1257 if (dpp_controller_rx_action(conn, pos + 1,
1258 wpabuf_len(conn->msg) - 1) < 0)
1259 dpp_connection_remove(conn);
1260 break;
1261 case WLAN_PA_GAS_INITIAL_REQ:
1262 if (dpp_controller_rx_gas_req(conn, pos + 1,
1263 wpabuf_len(conn->msg) - 1) < 0)
1264 dpp_connection_remove(conn);
1265 break;
1266 case WLAN_PA_GAS_INITIAL_RESP:
1267 if (dpp_rx_gas_resp(conn, pos + 1,
1268 wpabuf_len(conn->msg) - 1) < 0)
1269 dpp_connection_remove(conn);
1270 break;
1271 default:
1272 wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u",
1273 *pos);
1274 break;
1275 }
1276}
1277
1278
1279static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
1280{
1281 struct dpp_controller *ctrl = eloop_ctx;
1282 struct sockaddr_in addr;
1283 socklen_t addr_len = sizeof(addr);
1284 int fd;
1285 struct dpp_connection *conn;
1286
1287 wpa_printf(MSG_DEBUG, "DPP: New TCP connection");
1288
1289 fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len);
1290 if (fd < 0) {
1291 wpa_printf(MSG_DEBUG,
1292 "DPP: Failed to accept new connection: %s",
1293 strerror(errno));
1294 return;
1295 }
1296 wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
1297 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
1298
1299 conn = os_zalloc(sizeof(*conn));
1300 if (!conn)
1301 goto fail;
1302
1303 conn->global = ctrl->global;
1304 conn->ctrl = ctrl;
1305 conn->sock = fd;
1306
1307 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1308 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1309 strerror(errno));
1310 goto fail;
1311 }
1312
1313 if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
1314 dpp_controller_rx, conn, NULL) < 0)
1315 goto fail;
1316 conn->read_eloop = 1;
1317
1318 /* TODO: eloop timeout to expire connections that do not complete in
1319 * reasonable time */
1320 dl_list_add(&ctrl->conn, &conn->list);
1321 return;
1322
1323fail:
1324 close(fd);
1325 os_free(conn);
1326}
1327
1328
1329int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
1330 const struct hostapd_ip_addr *addr, int port)
1331{
1332 struct dpp_connection *conn;
1333 struct sockaddr_storage saddr;
1334 socklen_t addrlen;
1335 const u8 *hdr, *pos, *end;
1336 char txt[100];
1337
1338 wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
1339 hostapd_ip_txt(addr, txt, sizeof(txt)), port);
1340 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
1341 addr, port) < 0) {
1342 dpp_auth_deinit(auth);
1343 return -1;
1344 }
1345
1346 conn = os_zalloc(sizeof(*conn));
1347 if (!conn) {
1348 dpp_auth_deinit(auth);
1349 return -1;
1350 }
1351
1352 conn->global = dpp;
1353 conn->auth = auth;
1354 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
1355 if (conn->sock < 0)
1356 goto fail;
1357
1358 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1359 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1360 strerror(errno));
1361 goto fail;
1362 }
1363
1364 if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
1365 if (errno != EINPROGRESS) {
1366 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
1367 strerror(errno));
1368 goto fail;
1369 }
1370
1371 /*
1372 * Continue connecting in the background; eloop will call us
1373 * once the connection is ready (or failed).
1374 */
1375 }
1376
1377 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
1378 dpp_conn_tx_ready, conn, NULL) < 0)
1379 goto fail;
1380 conn->write_eloop = 1;
1381
1382 hdr = wpabuf_head(auth->req_msg);
1383 end = hdr + wpabuf_len(auth->req_msg);
1384 hdr += 2; /* skip Category and Actiom */
1385 pos = hdr + DPP_HDR_LEN;
1386 conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
1387 if (!conn->msg_out)
1388 goto fail;
1389 /* Message will be sent in dpp_conn_tx_ready() */
1390
1391 /* TODO: eloop timeout to clear a connection if it does not complete
1392 * properly */
1393 dl_list_add(&dpp->tcp_init, &conn->list);
1394 return 0;
1395fail:
1396 dpp_connection_free(conn);
1397 return -1;
1398}
1399
1400
1401int dpp_controller_start(struct dpp_global *dpp,
1402 struct dpp_controller_config *config)
1403{
1404 struct dpp_controller *ctrl;
1405 int on = 1;
1406 struct sockaddr_in sin;
1407 int port;
1408
1409 if (!dpp || dpp->controller)
1410 return -1;
1411
1412 ctrl = os_zalloc(sizeof(*ctrl));
1413 if (!ctrl)
1414 return -1;
1415 ctrl->global = dpp;
1416 if (config->configurator_params)
1417 ctrl->configurator_params =
1418 os_strdup(config->configurator_params);
1419 dl_list_init(&ctrl->conn);
1420 ctrl->allowed_roles = config->allowed_roles;
1421 ctrl->qr_mutual = 0;
1422
1423 ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
1424 if (ctrl->sock < 0)
1425 goto fail;
1426
1427 if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR,
1428 &on, sizeof(on)) < 0) {
1429 wpa_printf(MSG_DEBUG,
1430 "DPP: setsockopt(SO_REUSEADDR) failed: %s",
1431 strerror(errno));
1432 /* try to continue anyway */
1433 }
1434
1435 if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) {
1436 wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
1437 strerror(errno));
1438 goto fail;
1439 }
1440
1441 /* TODO: IPv6 */
1442 os_memset(&sin, 0, sizeof(sin));
1443 sin.sin_family = AF_INET;
1444 sin.sin_addr.s_addr = INADDR_ANY;
1445 port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT;
1446 sin.sin_port = htons(port);
1447 if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
1448 wpa_printf(MSG_INFO,
1449 "DPP: Failed to bind Controller TCP port: %s",
1450 strerror(errno));
1451 goto fail;
1452 }
1453 if (listen(ctrl->sock, 10 /* max backlog */) < 0 ||
1454 fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 ||
1455 eloop_register_sock(ctrl->sock, EVENT_TYPE_READ,
1456 dpp_controller_tcp_cb, ctrl, NULL))
1457 goto fail;
1458
1459 dpp->controller = ctrl;
1460 wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port);
1461 return 0;
1462fail:
1463 dpp_controller_free(ctrl);
1464 return -1;
1465}
1466
1467
1468void dpp_controller_stop(struct dpp_global *dpp)
1469{
1470 if (dpp) {
1471 dpp_controller_free(dpp->controller);
1472 dpp->controller = NULL;
1473 }
1474}
1475
1476
1477void dpp_tcp_init_flush(struct dpp_global *dpp)
1478{
1479 struct dpp_connection *conn, *tmp;
1480
1481 dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection,
1482 list)
1483 dpp_connection_remove(conn);
1484}
1485
1486
1487static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
1488{
1489 struct dpp_connection *conn, *tmp;
1490
1491 dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
1492 list)
1493 dpp_connection_remove(conn);
1494 os_free(ctrl);
1495}
1496
1497
1498void dpp_relay_flush_controllers(struct dpp_global *dpp)
1499{
1500 struct dpp_relay_controller *ctrl, *tmp;
1501
1502 if (!dpp)
1503 return;
1504
1505 dl_list_for_each_safe(ctrl, tmp, &dpp->controllers,
1506 struct dpp_relay_controller, list) {
1507 dl_list_del(&ctrl->list);
1508 dpp_relay_controller_free(ctrl);
1509 }
1510}
1511
1512#endif /* CONFIG_DPP2 */