linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Brian Gix <brian.gix@intel.com>
To: linux-bluetooth@vger.kernel.org
Cc: johan.hedberg@gmail.com, inga.stotland@intel.com,
	marcel@holtmann.org, brian.gix@intel.com
Subject: [PATCH BlueZ v6 08/26] mesh: Acceptor side provisioning implementation
Date: Fri, 28 Dec 2018 14:07:27 -0800	[thread overview]
Message-ID: <20181228220745.25147-9-brian.gix@intel.com> (raw)
In-Reply-To: <20181228220745.25147-1-brian.gix@intel.com>

This functionaility (originally found in provision.c) was rewritten
as the Acceptor side only of the provisioning procedure. This
is the more common procedure of the unprovisioned device that is
brought into an existing mesh network by a remote (master) Provisioner.
---
 mesh/prov-acceptor.c | 684 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 684 insertions(+)
 create mode 100644 mesh/prov-acceptor.c

diff --git a/mesh/prov-acceptor.c b/mesh/prov-acceptor.c
new file mode 100644
index 000000000..baa3c4d30
--- /dev/null
+++ b/mesh/prov-acceptor.c
@@ -0,0 +1,684 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2018  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <time.h>
+#include <ell/ell.h>
+
+#include "mesh/mesh-defs.h"
+#include "src/shared/ecc.h"
+
+#include "mesh/util.h"
+#include "mesh/net_keys.h"
+#include "mesh/crypto.h"
+#include "mesh/net.h"
+#include "mesh/error.h"
+#include "mesh/prov.h"
+#include "mesh/provision.h"
+#include "mesh/pb-adv.h"
+#include "mesh/mesh.h"
+#include "mesh/agent.h"
+
+/* Quick size sanity check */
+static const uint16_t expected_pdu_size[] = {
+	2,	/* PROV_INVITE */
+	12,	/* PROV_CAPS */
+	6,	/* PROV_START */
+	65,	/* PROV_PUB_KEY */
+	1,	/* PROV_INP_CMPLT */
+	17,	/* PROV_CONFIRM */
+	17,	/* PROV_RANDOM */
+	34,	/* PROV_DATA */
+	1,	/* PROV_COMPLETE */
+	2,	/* PROV_FAILED */
+};
+
+#define BEACON_TYPE_UNPROVISIONED		0x00
+
+static const uint8_t pkt_filter = MESH_AD_TYPE_PROVISION;
+static const uint8_t bec_filter[] = {MESH_AD_TYPE_BEACON,
+						BEACON_TYPE_UNPROVISIONED};
+
+enum acp_state {
+	ACP_PROV_IDLE = 0,
+	ACP_PROV_CAPS_SENT,
+	ACP_PROV_CAPS_ACKED,
+	ACP_PROV_KEY_SENT,
+	ACP_PROV_KEY_ACKED,
+	ACP_PROV_INP_CMPLT_SENT,
+	ACP_PROV_INP_CMPLT_ACKED,
+	ACP_PROV_CONF_SENT,
+	ACP_PROV_CONF_ACKED,
+	ACP_PROV_RAND_SENT,
+	ACP_PROV_RAND_ACKED,
+	ACP_PROV_CMPLT_SENT,
+	ACP_PROV_FAIL_SENT,
+};
+
+#define MAT_REMOTE_PUBLIC	0x01
+#define MAT_LOCAL_PRIVATE	0x02
+#define MAT_RAND_AUTH		0x04
+#define MAT_SECRET	(MAT_REMOTE_PUBLIC | MAT_LOCAL_PRIVATE)
+
+struct mesh_prov_acceptor {
+	mesh_prov_acceptor_complete_func_t cmplt;
+	prov_trans_tx_t trans_tx;
+	void *agent;
+	void *caller_data;
+	void *trans_data;
+	struct l_timeout *timeout;
+	uint32_t to_secs;
+	enum acp_state	state;
+	uint8_t transport;
+	uint8_t material;
+	uint8_t expected;
+	int8_t previous;
+	struct conf_input conf_inputs;
+	uint8_t calc_key[16];
+	uint8_t salt[16];
+	uint8_t confirm[16];
+	uint8_t s_key[16];
+	uint8_t s_nonce[13];
+	uint8_t private_key[32];
+	uint8_t secret[32];
+	uint8_t rand_auth_workspace[48];
+};
+
+static struct mesh_prov_acceptor *prov = NULL;
+
+static void acceptor_free(void)
+{
+
+	if (prov)
+		l_timeout_remove(prov->timeout);
+
+	mesh_send_cancel(bec_filter, sizeof(bec_filter));
+	mesh_send_cancel(&pkt_filter, sizeof(pkt_filter));
+
+	if (prov->trans_tx) {
+		if (prov->transport == PB_ADV)
+			pb_adv_unreg(prov->trans_data);
+	}
+
+	l_free(prov);
+	prov = NULL;
+}
+
+static void acp_prov_close(void *user_data, uint8_t reason)
+{
+	/* TODO: Handle Close */
+}
+
+static void prov_to(struct l_timeout *timeout, void *user_data)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t fail_code[2] = {PROV_FAILED, PROV_ERR_UNEXPECTED_ERR};
+
+	if (rx_prov != prov)
+		return;
+
+	prov->timeout = NULL;
+
+	if (prov->cmplt && prov->trans_tx) {
+		prov->cmplt(prov->caller_data, PROV_ERR_TIMEOUT, NULL);
+		prov->cmplt = NULL;
+		prov->trans_tx(prov->trans_data, fail_code, 2);
+		prov->timeout = l_timeout_create(1, prov_to, prov, NULL);
+		return;
+	}
+
+	acceptor_free();
+}
+
+static void acp_prov_open(void *user_data, prov_trans_tx_t trans_tx,
+				void *trans_data, uint8_t transport)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+
+	/* Only one provisioning session may be open at a time */
+	if (rx_prov != prov)
+		return;
+
+	/* Only one provisioning session may be open at a time */
+	if (prov->trans_tx && prov->trans_tx != trans_tx &&
+					prov->transport != transport)
+		return;
+
+	if (transport != PB_ADV)
+		return;
+
+	prov->trans_tx = trans_tx;
+	prov->transport = transport;
+	prov->trans_data = trans_data;
+	prov->timeout = l_timeout_create(prov->to_secs, prov_to, prov, NULL);
+}
+
+static void swap_u256_bytes(uint8_t *u256)
+{
+	int i;
+
+	/* End-to-End byte reflection of 32 octet buffer */
+	for (i = 0; i < 16; i++) {
+		u256[i] ^= u256[31 - i];
+		u256[31 - i] ^= u256[i];
+		u256[i] ^= u256[31 - i];
+	}
+}
+
+static void prov_calc_secret(const uint8_t *pub, const uint8_t *priv,
+							uint8_t *secret)
+{
+	uint8_t tmp[64];
+
+	/* Convert to ECC byte order */
+	memcpy(tmp, pub, 64);
+	swap_u256_bytes(tmp);
+	swap_u256_bytes(tmp + 32);
+
+	ecdh_shared_secret(tmp, priv, secret);
+
+	/* Convert to Mesh byte order */
+	swap_u256_bytes(secret);
+}
+
+static void acp_credentials(struct mesh_prov_acceptor *prov)
+{
+	prov_calc_secret(prov->conf_inputs.prv_pub_key,
+			prov->private_key, prov->secret);
+
+	mesh_crypto_s1(&prov->conf_inputs,
+			sizeof(prov->conf_inputs), prov->salt);
+
+	mesh_crypto_prov_conf_key(prov->secret, prov->salt,
+			prov->calc_key);
+
+	l_getrandom(prov->rand_auth_workspace, 16);
+
+	print_packet("PublicKeyProv", prov->conf_inputs.prv_pub_key, 64);
+	print_packet("PublicKeyDev", prov->conf_inputs.dev_pub_key, 64);
+	print_packet("PrivateKeyLocal", prov->private_key, 32);
+	print_packet("ConfirmationInputs", &prov->conf_inputs,
+						sizeof(prov->conf_inputs));
+	print_packet("ECDHSecret", prov->secret, 32);
+	print_packet("LocalRandom", prov->rand_auth_workspace, 16);
+	print_packet("ConfirmationSalt", prov->salt, 16);
+	print_packet("ConfirmationKey", prov->calc_key, 16);
+}
+
+static uint32_t digit_mod(uint8_t power)
+{
+	uint32_t ret = 1;
+
+	while (power--)
+		ret *= 10;
+
+	return ret;
+}
+
+static void number_cb(void *user_data, int err, uint32_t number)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t out[2];
+
+	if (prov != rx_prov)
+		return;
+
+	if (err) {
+		out[0] = PROV_FAILED;
+		out[1] = PROV_ERR_UNEXPECTED_ERR;
+		prov->trans_tx(prov->trans_data, out, 2);
+		return;
+	}
+
+	/* Save two copies, to generate two confirmation values */
+	l_put_be32(number, prov->rand_auth_workspace + 28);
+	l_put_be32(number, prov->rand_auth_workspace + 44);
+	prov->material |= MAT_RAND_AUTH;
+	out[0] = PROV_INP_CMPLT;
+	prov->trans_tx(prov->trans_data, out, 1);
+}
+
+static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t out[2];
+
+	if (prov != rx_prov)
+		return;
+
+	if (err || !key || len != 16) {
+		out[0] = PROV_FAILED;
+		out[1] = PROV_ERR_UNEXPECTED_ERR;
+		prov->trans_tx(prov->trans_data, out, 2);
+		return;
+	}
+
+	/* Save two copies, to generate two confirmation values */
+	memcpy(prov->rand_auth_workspace + 16, key, 16);
+	memcpy(prov->rand_auth_workspace + 32, key, 16);
+	prov->material |= MAT_RAND_AUTH;
+}
+
+static void priv_key_cb(void *user_data, int err, uint8_t *key, uint32_t len)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	uint8_t out[2];
+
+	if (prov != rx_prov)
+		return;
+
+	if (err || !key || len != 32) {
+		out[0] = PROV_FAILED;
+		out[1] = PROV_ERR_UNEXPECTED_ERR;
+		prov->trans_tx(prov->trans_data, out, 2);
+		return;
+	}
+
+	memcpy(prov->private_key, key, 32);
+	ecc_make_public_key(prov->private_key,
+			prov->conf_inputs.dev_pub_key);
+
+	/* Convert to Mesh byte order */
+	swap_u256_bytes(prov->conf_inputs.dev_pub_key);
+	swap_u256_bytes(prov->conf_inputs.dev_pub_key + 32);
+
+	prov->material |= MAT_LOCAL_PRIVATE;
+	if ((prov->material & MAT_SECRET) == MAT_SECRET)
+		acp_credentials(prov);
+}
+
+static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len)
+{
+	struct mesh_prov_acceptor *rx_prov = user_data;
+	struct mesh_prov_node_info *info;
+	uint8_t *out;
+	uint8_t type = *data++;
+	uint8_t fail_code[2];
+	uint32_t oob_key;
+	uint64_t decode_mic;
+	bool result;
+
+	if (rx_prov != prov || !prov->trans_tx)
+		return;
+
+	l_debug("Provisioning packet received type: %2.2x (%u octets)",
+								type, len);
+
+	if (type == prov->previous) {
+		l_error("Ignore repeated %2.2x packet", type);
+		return;
+	} else if (type > prov->expected || type < prov->previous) {
+		l_error("Expected %2.2x, Got:%2.2x", prov->expected, type);
+		fail_code[1] = PROV_ERR_UNEXPECTED_PDU;
+		goto failure;
+	}
+
+	if (type >= L_ARRAY_SIZE(expected_pdu_size) ||
+					len != expected_pdu_size[type]) {
+		l_error("Expected PDU size %d, Got %d (type: %2.2x)",
+			len, expected_pdu_size[type], type);
+		fail_code[1] = PROV_ERR_INVALID_FORMAT;
+		goto failure;
+	}
+
+	switch (type){
+	case PROV_INVITE: /* Prov Invite */
+		/* Prov Capabilities */
+		out = l_malloc(1 + sizeof(struct mesh_net_prov_caps));
+		out[0] = PROV_CAPS;
+		memcpy(out + 1, &prov->conf_inputs.caps,
+					sizeof(prov->conf_inputs.caps));
+
+		prov->conf_inputs.invite.attention = data[0];
+
+		prov->state = ACP_PROV_CAPS_SENT;
+		prov->expected = PROV_START;
+		prov->trans_tx(prov->trans_data,
+				out, sizeof(prov->conf_inputs.caps) + 1);
+		l_free(out);
+		break;
+
+	case PROV_START: /* Prov Start */
+		memcpy(&prov->conf_inputs.start, data,
+				sizeof(prov->conf_inputs.start));
+
+		if (prov->conf_inputs.start.algorithm ||
+				prov->conf_inputs.start.pub_key > 1 ||
+				prov->conf_inputs.start.auth_method > 3) {
+			fail_code[1] = PROV_ERR_INVALID_FORMAT;
+			goto failure;
+		}
+
+		if (prov->conf_inputs.start.pub_key) {
+			if (prov->conf_inputs.caps.pub_type) {
+				/* Prompt Agent for Private Key of OOB */
+				mesh_agent_request_private_key(prov->agent,
+							priv_key_cb, prov);
+			} else {
+				fail_code[1] = PROV_ERR_INVALID_PDU;
+				goto failure;
+			}
+		} else {
+			/* Ephemeral Public Key requested */
+			ecc_make_key(prov->conf_inputs.dev_pub_key,
+					prov->private_key);
+			swap_u256_bytes(prov->conf_inputs.dev_pub_key);
+			swap_u256_bytes(prov->conf_inputs.dev_pub_key + 32);
+			prov->material |= MAT_LOCAL_PRIVATE;
+		}
+
+		prov->expected = PROV_PUB_KEY;
+		break;
+
+	case PROV_PUB_KEY: /* Public Key */
+		/* Save Key */
+		memcpy(prov->conf_inputs.prv_pub_key, data, 64);
+		prov->material |= MAT_REMOTE_PUBLIC;
+		prov->expected = PROV_CONFIRM;
+
+		if ((prov->material & MAT_SECRET) != MAT_SECRET)
+			return;
+
+		acp_credentials(prov);
+
+		if (!prov->conf_inputs.start.pub_key) {
+			out = l_malloc(65);
+			out[0] = PROV_PUB_KEY;
+			memcpy(out + 1, prov->conf_inputs.dev_pub_key, 64);
+			prov->trans_tx(prov->trans_data, out, 65);
+			l_free(out);
+		}
+
+		/* Start Step 3 */
+		switch (prov->conf_inputs.start.auth_method) {
+		default:
+		case 0:
+			/* Auth Type 3c - No OOB */
+			break;
+
+		case 1:
+			/* Auth Type 3c - Static OOB */
+			/* Prompt Agent for Static OOB */
+			fail_code[1] = mesh_agent_request_static(prov->agent,
+					static_cb, prov);
+
+			if (fail_code[1])
+				goto failure;
+
+			break;
+
+		case 2:
+			/* Auth Type 3a - Output OOB */
+			l_getrandom(&oob_key, sizeof(oob_key));
+			oob_key %= digit_mod(prov->conf_inputs.start.auth_size);
+
+			/* Save two copies, for two confirmation values */
+			l_put_be32(oob_key, prov->rand_auth_workspace + 28);
+			l_put_be32(oob_key, prov->rand_auth_workspace + 44);
+			prov->material |= MAT_RAND_AUTH;
+
+			if (prov->conf_inputs.start.auth_action ==
+							PROV_ACTION_OUT_ALPHA) {
+				/* TODO: Construst NUL-term string to pass */
+				fail_code[1] = mesh_agent_display_string(
+					prov->agent, NULL, NULL, prov);
+			} else {
+				/* Ask Agent to Display U32 */
+				fail_code[1] = mesh_agent_display_number(
+					prov->agent, false,
+					prov->conf_inputs.start.auth_action,
+					oob_key, NULL, prov);
+			}
+
+			if (fail_code[1])
+				goto failure;
+
+			break;
+
+		case 3:
+			/* Auth Type 3b - input OOB */
+			/* Prompt Agent for Input OOB */
+			if (prov->conf_inputs.start.auth_action ==
+							PROV_ACTION_IN_ALPHA) {
+				fail_code[1] = mesh_agent_prompt_alpha(
+					prov->agent,
+					static_cb, prov);
+			} else {
+				fail_code[1] = mesh_agent_prompt_number(
+					prov->agent, false,
+					prov->conf_inputs.start.auth_action,
+					number_cb, prov);
+			}
+
+			if (fail_code[1])
+				goto failure;
+
+			break;
+		}
+
+		prov->expected = PROV_CONFIRM;
+		break;
+
+	case PROV_CONFIRM: /* Confirmation */
+		out = l_malloc(17);
+		out[0] = PROV_CONFIRM;
+
+		/* Calculate and Send our Confirmation */
+		mesh_crypto_aes_cmac(prov->calc_key, prov->rand_auth_workspace,
+								32, out + 1);
+		prov->trans_tx(prov->trans_data, out, 17);
+		l_free(out);
+
+		/* Save Provisioners confirmation for later compare */
+		memcpy(prov->confirm, data, 16);
+		prov->expected = PROV_RANDOM;
+		break;
+
+	case PROV_RANDOM: /* Random Value */
+		out = l_malloc(17);
+		/* Calculate Session key (needed later) while data is fresh */
+		mesh_crypto_prov_prov_salt(prov->salt, data,
+						prov->rand_auth_workspace,
+						prov->salt);
+		mesh_crypto_session_key(prov->secret, prov->salt, prov->s_key);
+		mesh_crypto_nonce(prov->secret, prov->salt, prov->s_nonce);
+
+		/* Calculate expected Provisioner Confirm */
+		memcpy(prov->rand_auth_workspace + 16, data, 16);
+		mesh_crypto_aes_cmac(prov->calc_key,
+				prov->rand_auth_workspace + 16, 32, out);
+
+		/* Compare our calculation with Provisioners */
+		if (memcmp(out, prov->confirm, 16)) {
+			fail_code[1] = PROV_ERR_CONFIRM_FAILED;
+			l_free(out);
+			goto failure;
+		}
+
+		/* Send Random value we used */
+		out[0] = PROV_RANDOM;
+		memcpy(out + 1, prov->rand_auth_workspace, 16);
+		prov->trans_tx(prov->trans_data, out, 17);
+		l_free(out);
+		prov->expected = PROV_DATA;
+		break;
+
+	case PROV_DATA: /* Provisioning Data */
+
+		/* Calculate our device key */
+		mesh_crypto_device_key(prov->secret,
+				prov->salt,
+				prov->calc_key);
+
+		/* Decrypt new node data into workspace */
+		mesh_crypto_aes_ccm_decrypt(prov->s_nonce, prov->s_key,
+				NULL, 0,
+				data, len - 1, prov->rand_auth_workspace,
+				&decode_mic, sizeof(decode_mic));
+
+		/* Validate that the data hasn't been messed with in transit */
+		if (l_get_be64(data + 25) != decode_mic) {
+			l_error("Provisioning Failed-MIC compare");
+			fail_code[1] = PROV_ERR_DECRYPT_FAILED;
+			goto failure;
+		}
+
+		info = l_malloc(sizeof(struct mesh_prov_node_info));
+
+		memcpy(info->device_key, prov->calc_key, 16);
+		memcpy(info->net_key, prov->rand_auth_workspace, 16);
+		info->net_index = l_get_be16(prov->rand_auth_workspace + 16);
+		info->flags = prov->rand_auth_workspace[18];
+		info->iv_index = l_get_be32(prov->rand_auth_workspace + 19);
+		info->unicast = l_get_be16(prov->rand_auth_workspace + 23);
+
+		result = prov->cmplt(prov->caller_data, PROV_ERR_SUCCESS, info);
+		prov->cmplt = NULL;
+		l_free(info);
+
+		if (result) {
+			prov->rand_auth_workspace[0] = PROV_COMPLETE;
+			prov->trans_tx(prov->trans_data,
+					prov->rand_auth_workspace, 1);
+			goto cleanup;
+		} else {
+			fail_code[1] = PROV_ERR_UNEXPECTED_ERR;
+			goto failure;
+		}
+		break;
+
+	case PROV_FAILED: /* Provisioning Error -- abort */
+		/* TODO: Call Complete Callback (Fail)*/
+		prov->cmplt(prov->caller_data,
+				data[0] ? data[0] : PROV_ERR_UNEXPECTED_ERR,
+				NULL);
+		prov->cmplt = NULL;
+		goto cleanup;
+	}
+
+	prov->previous = type;
+	return;
+
+failure:
+	fail_code[0] = PROV_FAILED;
+	prov->trans_tx(prov->trans_data, fail_code, 2);
+	if (prov->cmplt)
+		prov->cmplt(prov->caller_data, fail_code[1], NULL);
+	prov->cmplt = NULL;
+
+cleanup:
+	l_timeout_remove(prov->timeout);
+
+	/* Give PB Link 5 seconds to end session */
+	prov->timeout = l_timeout_create(5, prov_to, prov, NULL);
+}
+
+static void acp_prov_ack(void *user_data, uint8_t msg_num)
+{
+	/* TODO: Handle PB-ADV Ack */
+}
+
+
+/* This starts unprovisioned device beacon */
+bool acceptor_start(uint8_t num_ele, uint8_t uuid[16],
+		uint16_t algorithms, uint32_t timeout,
+		struct mesh_agent *agent,
+		mesh_prov_acceptor_complete_func_t complete_cb,
+		void *caller_data)
+{
+	struct mesh_agent_prov_caps *caps;
+	uint8_t beacon[24] = {MESH_AD_TYPE_BEACON,
+						BEACON_TYPE_UNPROVISIONED};
+	uint8_t len = sizeof(beacon) - sizeof(uint32_t);
+	bool result;
+
+	/* Invoked from Join() method in mesh-api.txt, to join a
+	 * remote mesh network.
+	 */
+
+	if (prov)
+		return false;
+
+	prov = l_new(struct mesh_prov_acceptor, 1);
+	prov->to_secs = timeout;
+	prov->agent = agent;
+	prov->cmplt = complete_cb;
+	prov->previous = -1;
+	prov->caller_data = caller_data;
+
+	caps = mesh_agent_get_caps(agent);
+
+	/* TODO: Should we sanity check values here or elsewhere? */
+	prov->conf_inputs.caps.num_ele = num_ele;
+	prov->conf_inputs.caps.pub_type = caps->pub_type;
+	prov->conf_inputs.caps.static_type = caps->static_type;
+	prov->conf_inputs.caps.output_size = caps->output_size;
+	prov->conf_inputs.caps.input_size = caps->input_size;
+
+	/* Store UINT16 values in Over-the-Air order, in packed structure
+	 * for crypto inputs
+	 */
+	l_put_be16(algorithms, &prov->conf_inputs.caps.algorithms);
+	l_put_be16(caps->output_action, &prov->conf_inputs.caps.output_action);
+	l_put_be16(caps->input_action, &prov->conf_inputs.caps.input_action);
+
+	/* Compose Unprovisioned Beacon */
+	memcpy(beacon + 2, uuid, 16);
+	l_put_be16(caps->oob_info, beacon + 18);
+	if (caps->oob_info & OOB_INFO_URI_HASH){
+		l_put_be32(caps->uri_hash, beacon + 20);
+		len += sizeof(uint32_t);
+	}
+
+	/* Infinitely Beacon until Canceled, or Provisioning Starts */
+	result = mesh_send_pkt(0, 500, beacon, len);
+
+	if (!result)
+		goto error_fail;
+
+	/* Always register for PB-ADV */
+	result = pb_adv_reg(acp_prov_open, acp_prov_close, acp_prov_rx,
+						acp_prov_ack, uuid, prov);
+
+	if (result)
+		return true;
+
+error_fail:
+	acceptor_free();
+	return false;
+}
+
+void acceptor_cancel(void *user_data)
+{
+	acceptor_free();
+}
-- 
2.14.5


  parent reply	other threads:[~2018-12-28 22:07 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-28 22:07 [PATCH BlueZ v6 00/26] Major rewrite for Multi-Node and DBus Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 01/26] mesh: Structural changes for mesh Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 02/26] mesh: Utilities for DBus support Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 03/26] mesh: Internal errors Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 04/26] mesh: Rewrite storage for Multiple Nodes Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 05/26] mesh: Rewrite Node handling for multiple nodes Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 06/26] mesh: Rewrite Network layer " Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 07/26] mesh: Direction agnostic PB-ADV implementation Brian Gix
2018-12-28 22:07 ` Brian Gix [this message]
2018-12-28 22:07 ` [PATCH BlueZ v6 09/26] mesh: Initiator side provisioning implementation Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 10/26] mesh: Rewrite Controler interface for full init Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 11/26] mesh: Unchanged variables set to const Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 12/26] mesh: Hex-String manipulation, and debug logging Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 13/26] mesh: re-arrange provisioning for DBus API Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 14/26] mesh: Re-architect " Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 15/26] mesh: Multi node Config Server model Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 16/26] mesh: restructure I/O for multiple nodes Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 17/26] mesh: Restructure DB to support " Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 18/26] mesh: Restructure model services for " Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 19/26] mesh: DBUS interface for Provisioning Agent Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 20/26] mesh: restructure App Key storage Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 21/26] mesh: Clean-up Comment style Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 22/26] mesh: Update for DBus API and multi-node support Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 23/26] mesh: Add default location for Mesh Node storage Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 24/26] mesh: Sample Provisioning Agent Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 25/26] mesh: Sample On/Off Client and Server Brian Gix
2018-12-28 22:07 ` [PATCH BlueZ v6 26/26] mesh: Sample Mesh Joiner (provision acceptor) Brian Gix

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181228220745.25147-9-brian.gix@intel.com \
    --to=brian.gix@intel.com \
    --cc=inga.stotland@intel.com \
    --cc=johan.hedberg@gmail.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=marcel@holtmann.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).