Blame tools/oobtest.c

Packit 34410b
/*
Packit 34410b
 *
Packit 34410b
 *  BlueZ - Bluetooth protocol stack for Linux
Packit 34410b
 *
Packit 34410b
 *  Copyright (C) 2011-2012  Intel Corporation
Packit 34410b
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
Packit 34410b
 *
Packit 34410b
 *
Packit 34410b
 *  This program is free software; you can redistribute it and/or modify
Packit 34410b
 *  it under the terms of the GNU General Public License as published by
Packit 34410b
 *  the Free Software Foundation; either version 2 of the License, or
Packit 34410b
 *  (at your option) any later version.
Packit 34410b
 *
Packit 34410b
 *  This program is distributed in the hope that it will be useful,
Packit 34410b
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 34410b
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 34410b
 *  GNU General Public License for more details.
Packit 34410b
 *
Packit 34410b
 *  You should have received a copy of the GNU General Public License
Packit 34410b
 *  along with this program; if not, write to the Free Software
Packit 34410b
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit 34410b
 *
Packit 34410b
 */
Packit 34410b
Packit 34410b
#ifdef HAVE_CONFIG_H
Packit 34410b
#include <config.h>
Packit 34410b
#endif
Packit 34410b
Packit 34410b
#include <getopt.h>
Packit 34410b
Packit 34410b
#include "lib/bluetooth.h"
Packit 34410b
#include "lib/mgmt.h"
Packit 34410b
Packit 34410b
#include "src/shared/mainloop.h"
Packit 34410b
#include "src/shared/util.h"
Packit 34410b
#include "src/shared/mgmt.h"
Packit 34410b
#include "src/shared/crypto.h"
Packit 34410b
Packit 34410b
#define REMOTE_IRK	"\x69\x30\xde\xc3\x8f\x84\x74\x14" \
Packit 34410b
			"\xe1\x23\x99\xc1\xca\x9a\xc3\x31"
Packit 34410b
Packit 34410b
static bool use_bredr = false;
Packit 34410b
static bool use_le = false;
Packit 34410b
static bool use_sc = false;
Packit 34410b
static bool use_sconly = false;
Packit 34410b
static bool use_legacy = false;
Packit 34410b
static bool use_random = false;
Packit 34410b
static bool use_privacy = false;
Packit 34410b
static bool use_debug = false;
Packit 34410b
static bool use_cross = false;
Packit 34410b
static bool provide_tk = false;
Packit 34410b
static bool provide_p192 = false;
Packit 34410b
static bool provide_p256 = false;
Packit 34410b
static bool provide_initiator = false;
Packit 34410b
static bool provide_acceptor = false;
Packit 34410b
Packit 34410b
static struct mgmt *mgmt;
Packit 34410b
static uint16_t index1 = MGMT_INDEX_NONE;
Packit 34410b
static uint16_t index2 = MGMT_INDEX_NONE;
Packit 34410b
static bdaddr_t bdaddr1;
Packit 34410b
static bdaddr_t bdaddr2;
Packit 34410b
static uint8_t oob_tk[16];
Packit 34410b
Packit 34410b
static void pin_code_request_event(uint16_t index, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_ev_pin_code_request *ev = param;
Packit 34410b
	struct mgmt_cp_pin_code_reply cp;
Packit 34410b
	char str[18];
Packit 34410b
Packit 34410b
	ba2str(&ev->addr.bdaddr, str);
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
	printf("  Pin code request: %s\n", str);
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
Packit 34410b
	cp.pin_len = 4;
Packit 34410b
	memset(cp.pin_code, '0', 4);
Packit 34410b
Packit 34410b
	mgmt_reply(mgmt, MGMT_OP_PIN_CODE_REPLY, index, sizeof(cp), &cp,
Packit 34410b
							NULL, NULL, NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void new_link_key_event(uint16_t index, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_ev_new_link_key *ev = param;
Packit 34410b
	const char *type;
Packit 34410b
	char str[18];
Packit 34410b
	int i;
Packit 34410b
Packit 34410b
	ba2str(&ev->key.addr.bdaddr, str);
Packit 34410b
Packit 34410b
	switch (ev->key.type) {
Packit 34410b
	case 0x00:
Packit 34410b
		type = "Legacy";
Packit 34410b
		break;
Packit 34410b
	case 0x01:
Packit 34410b
		type = "Local Unit";
Packit 34410b
		break;
Packit 34410b
	case 0x02:
Packit 34410b
		type = "Remote Unit";
Packit 34410b
		break;
Packit 34410b
	case 0x03:
Packit 34410b
		type = "Debug";
Packit 34410b
		break;
Packit 34410b
	case 0x04:
Packit 34410b
		type = "Unauthenticated, P-192";
Packit 34410b
		break;
Packit 34410b
	case 0x05:
Packit 34410b
		type = "Authenticated, P-192";
Packit 34410b
		break;
Packit 34410b
	case 0x06:
Packit 34410b
		type = "Changed";
Packit 34410b
		break;
Packit 34410b
	case 0x07:
Packit 34410b
		type = "Unauthenticated, P-256";
Packit 34410b
		break;
Packit 34410b
	case 0x08:
Packit 34410b
		type = "Authenticated, P-256";
Packit 34410b
		break;
Packit 34410b
	default:
Packit 34410b
		type = "<unknown>";
Packit 34410b
		break;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
	printf("  New link key: %s\n", str);
Packit 34410b
	printf("  Type: %s (%u)\n", type, ev->key.type);
Packit 34410b
	printf("  Key: ");
Packit 34410b
	for (i = 0; i < 16; i++)
Packit 34410b
		printf("%02x", ev->key.val[i]);
Packit 34410b
	printf("\n");
Packit 34410b
}
Packit 34410b
Packit 34410b
static void new_long_term_key_event(uint16_t index, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_ev_new_long_term_key *ev = param;
Packit 34410b
	const char *type;
Packit 34410b
	char str[18];
Packit 34410b
	int i;
Packit 34410b
Packit 34410b
	ba2str(&ev->key.addr.bdaddr, str);
Packit 34410b
Packit 34410b
	switch (ev->key.type) {
Packit 34410b
	case 0x00:
Packit 34410b
		if (ev->key.master)
Packit 34410b
			type = "Unauthenticated, Master";
Packit 34410b
		else
Packit 34410b
			type = "Unauthenticated, Slave";
Packit 34410b
		break;
Packit 34410b
	case 0x01:
Packit 34410b
		if (ev->key.master)
Packit 34410b
			type = "Authenticated, Master";
Packit 34410b
		else
Packit 34410b
			type = "Authenticated, Slave";
Packit 34410b
		break;
Packit 34410b
	case 0x02:
Packit 34410b
		type = "Unauthenticated, P-256";
Packit 34410b
		break;
Packit 34410b
	case 0x03:
Packit 34410b
		type = "Authenticated, P-256";
Packit 34410b
		break;
Packit 34410b
	case 0x04:
Packit 34410b
		type = "Debug";
Packit 34410b
		break;
Packit 34410b
	default:
Packit 34410b
		type = "<unknown>";
Packit 34410b
		break;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
	printf("  New long term key: %s\n", str);
Packit 34410b
	printf("  Type: %s (%u)\n", type, ev->key.type);
Packit 34410b
	printf("  Key: ");
Packit 34410b
	for (i = 0; i < 16; i++)
Packit 34410b
		printf("%02x", ev->key.val[i]);
Packit 34410b
	printf("\n");
Packit 34410b
}
Packit 34410b
Packit 34410b
static void pair_device_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Pair device from index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
	}
Packit 34410b
Packit 34410b
	mainloop_quit();
Packit 34410b
}
Packit 34410b
Packit 34410b
static void pair_device(uint16_t index, const bdaddr_t *bdaddr)
Packit 34410b
{
Packit 34410b
	struct mgmt_cp_pair_device cp;
Packit 34410b
	char str[18];
Packit 34410b
Packit 34410b
	ba2str(bdaddr, str);
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
	printf("  Starting pairing: %s\n", str);
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	bacpy(&cp.addr.bdaddr, bdaddr);
Packit 34410b
	if (use_bredr)
Packit 34410b
		cp.addr.type = BDADDR_BREDR;
Packit 34410b
	else if (use_random)
Packit 34410b
		cp.addr.type = BDADDR_LE_RANDOM;
Packit 34410b
	else
Packit 34410b
		cp.addr.type = BDADDR_LE_PUBLIC;
Packit 34410b
	cp.io_cap = 0x03;
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_PAIR_DEVICE, index, sizeof(cp), &cp,
Packit 34410b
						pair_device_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void add_remote_oob_data_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_addr_info *rp = param;
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
	char str[18];
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Adding OOB data for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
	}
Packit 34410b
Packit 34410b
	ba2str(&rp->bdaddr, str);
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
	printf("  Remote data added: %s\n", str);
Packit 34410b
Packit 34410b
	if (index == index1) {
Packit 34410b
		uint8_t val = 0x01;
Packit 34410b
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_CONNECTABLE, index2, 1, &val,
Packit 34410b
							NULL, NULL, NULL);
Packit 34410b
Packit 34410b
		if (use_le)
Packit 34410b
			mgmt_send(mgmt, MGMT_OP_SET_ADVERTISING, index2,
Packit 34410b
						1, &val, NULL, NULL, NULL);
Packit 34410b
Packit 34410b
		pair_device(index1, &bdaddr2);
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void add_remote_oob_data(uint16_t index, const bdaddr_t *bdaddr,
Packit 34410b
				const uint8_t *hash192, const uint8_t *rand192,
Packit 34410b
				const uint8_t *hash256, const uint8_t *rand256)
Packit 34410b
{
Packit 34410b
	struct mgmt_cp_add_remote_oob_data cp;
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	bacpy(&cp.addr.bdaddr, bdaddr);
Packit 34410b
	if (use_bredr)
Packit 34410b
		cp.addr.type = BDADDR_BREDR;
Packit 34410b
	else if (use_random)
Packit 34410b
		cp.addr.type = BDADDR_LE_RANDOM;
Packit 34410b
	else
Packit 34410b
		cp.addr.type = BDADDR_LE_PUBLIC;
Packit 34410b
	if (hash192) {
Packit 34410b
		memcpy(cp.hash192, hash192, 16);
Packit 34410b
		if (rand192)
Packit 34410b
			memcpy(cp.rand192, rand192, 16);
Packit 34410b
		else
Packit 34410b
			memset(cp.rand192, 0, 16);
Packit 34410b
	} else {
Packit 34410b
		memset(cp.hash192, 0, 16);
Packit 34410b
		memset(cp.rand192, 0, 16);
Packit 34410b
	}
Packit 34410b
	if (hash256 && rand256) {
Packit 34410b
		memcpy(cp.hash256, hash256, 16);
Packit 34410b
		memcpy(cp.rand256, rand256, 16);
Packit 34410b
	} else {
Packit 34410b
		memset(cp.hash256, 0, 16);
Packit 34410b
		memset(cp.rand256, 0, 16);
Packit 34410b
	}
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_ADD_REMOTE_OOB_DATA, index, sizeof(cp), &cp,
Packit 34410b
						add_remote_oob_data_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void read_oob_data_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_rp_read_local_oob_data *rp = param;
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
	const uint8_t *hash192, *rand192, *hash256, *rand256;
Packit 34410b
	int i;
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Reading OOB data for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
Packit 34410b
	hash192 = NULL;
Packit 34410b
	rand192 = NULL;
Packit 34410b
	hash256 = NULL;
Packit 34410b
	rand256 = NULL;
Packit 34410b
Packit 34410b
	if (index == index1 && !provide_initiator) {
Packit 34410b
		printf("  Skipping initiator OOB data\n");
Packit 34410b
		goto done;
Packit 34410b
	} else if (index == index2 && !provide_acceptor) {
Packit 34410b
		printf("  Skipping acceptor OOB data\n");
Packit 34410b
		goto done;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (provide_p192) {
Packit 34410b
		hash192 = rp->hash192;
Packit 34410b
		rand192 = rp->rand192;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("  Hash C from P-192: ");
Packit 34410b
	for (i = 0; i < 16; i++)
Packit 34410b
		printf("%02x", rp->hash192[i]);
Packit 34410b
	printf("\n");
Packit 34410b
Packit 34410b
	printf("  Randomizer R with P-192: ");
Packit 34410b
	for (i = 0; i < 16; i++)
Packit 34410b
		printf("%02x", rp->rand192[i]);
Packit 34410b
	printf("\n");
Packit 34410b
Packit 34410b
	if (len < sizeof(*rp))
Packit 34410b
		goto done;
Packit 34410b
Packit 34410b
	if (provide_p256) {
Packit 34410b
		hash256 = rp->hash256;
Packit 34410b
		rand256 = rp->rand256;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("  Hash C from P-256: ");
Packit 34410b
	for (i = 0; i < 16; i++)
Packit 34410b
		printf("%02x", rp->hash256[i]);
Packit 34410b
	printf("\n");
Packit 34410b
Packit 34410b
	printf("  Randomizer R with P-256: ");
Packit 34410b
	for (i = 0; i < 16; i++)
Packit 34410b
		printf("%02x", rp->rand256[i]);
Packit 34410b
	printf("\n");
Packit 34410b
Packit 34410b
done:
Packit 34410b
	if (index == index1)
Packit 34410b
		add_remote_oob_data(index2, &bdaddr1,
Packit 34410b
					hash192, rand192, hash256, rand256);
Packit 34410b
	else if (index == index2)
Packit 34410b
		add_remote_oob_data(index1, &bdaddr2,
Packit 34410b
					hash192, rand192, hash256, rand256);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void read_oob_ext_data_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_rp_read_local_oob_ext_data *rp = param;
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
	uint16_t eir_len, parsed;
Packit 34410b
	const uint8_t *eir, *tk, *hash256, *rand256;
Packit 34410b
	int i;
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Reading OOB data for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
Packit 34410b
	eir_len = le16_to_cpu(rp->eir_len);
Packit 34410b
	printf("  OOB data len: %u\n", eir_len);
Packit 34410b
Packit 34410b
	if (provide_tk)
Packit 34410b
		tk = oob_tk;
Packit 34410b
	else
Packit 34410b
		tk = NULL;
Packit 34410b
Packit 34410b
	hash256 = NULL;
Packit 34410b
	rand256 = NULL;
Packit 34410b
Packit 34410b
	if (index == index1 && !provide_initiator) {
Packit 34410b
		printf("  Skipping initiator OOB data\n");
Packit 34410b
		goto done;
Packit 34410b
	} else if (index == index2 && !provide_acceptor) {
Packit 34410b
		printf("  Skipping acceptor OOB data\n");
Packit 34410b
		goto done;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (eir_len < 2)
Packit 34410b
		goto done;
Packit 34410b
Packit 34410b
	eir = rp->eir;
Packit 34410b
	parsed = 0;
Packit 34410b
Packit 34410b
	while (parsed < eir_len - 1) {
Packit 34410b
		uint8_t field_len = eir[0];
Packit 34410b
Packit 34410b
		if (field_len == 0)
Packit 34410b
			break;
Packit 34410b
Packit 34410b
		parsed += field_len + 1;
Packit 34410b
Packit 34410b
		if (parsed > eir_len)
Packit 34410b
			break;
Packit 34410b
Packit 34410b
		/* LE Bluetooth Device Address */
Packit 34410b
		if (eir[1] == 0x1b) {
Packit 34410b
			char str[18];
Packit 34410b
Packit 34410b
			ba2str((bdaddr_t *) (eir + 2), str);
Packit 34410b
			printf("  Device address: %s (%s)\n", str,
Packit 34410b
						eir[8] ? "random" : "public");
Packit 34410b
		}
Packit 34410b
Packit 34410b
		/* LE Role */
Packit 34410b
		if (eir[1] == 0x1c)
Packit 34410b
			printf("  Role: 0x%02x\n", eir[2]);
Packit 34410b
Packit 34410b
		/* LE Secure Connections Confirmation Value */
Packit 34410b
		if (eir[1] == 0x22) {
Packit 34410b
			hash256 = eir + 2;
Packit 34410b
Packit 34410b
			printf("  Hash C from P-256: ");
Packit 34410b
			for (i = 0; i < 16; i++)
Packit 34410b
				printf("%02x", hash256[i]);
Packit 34410b
			printf("\n");
Packit 34410b
		}
Packit 34410b
Packit 34410b
		/* LE Secure Connections Random Value */
Packit 34410b
		if (eir[1] == 0x23) {
Packit 34410b
			rand256 = eir + 2;
Packit 34410b
Packit 34410b
			printf("  Randomizer R with P-256: ");
Packit 34410b
			for (i = 0; i < 16; i++)
Packit 34410b
				printf("%02x", rand256[i]);
Packit 34410b
			printf("\n");
Packit 34410b
		}
Packit 34410b
Packit 34410b
		eir += field_len + 1;
Packit 34410b
	}
Packit 34410b
Packit 34410b
done:
Packit 34410b
	if (index == index1)
Packit 34410b
		add_remote_oob_data(index2, &bdaddr1,
Packit 34410b
					tk, NULL, hash256, rand256);
Packit 34410b
	else if (index == index2)
Packit 34410b
		add_remote_oob_data(index1, &bdaddr2,
Packit 34410b
					tk, NULL, hash256, rand256);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_powered_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
	uint32_t settings;
Packit 34410b
	uint8_t val;
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Powering on for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	settings = get_le32(param);
Packit 34410b
Packit 34410b
	if (!(settings & MGMT_SETTING_POWERED)) {
Packit 34410b
		fprintf(stderr, "Controller is not powered\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_debug) {
Packit 34410b
		if (index == index1) {
Packit 34410b
			val = 0x02;
Packit 34410b
			mgmt_send(mgmt, MGMT_OP_SET_DEBUG_KEYS, index, 1, &val,
Packit 34410b
							NULL, NULL, NULL);
Packit 34410b
		} else if (index == index2) {
Packit 34410b
			val = 0x01;
Packit 34410b
			mgmt_send(mgmt, MGMT_OP_SET_DEBUG_KEYS, index, 1, &val,
Packit 34410b
							NULL, NULL, NULL);
Packit 34410b
		}
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_bredr && (provide_p192 || provide_p256)) {
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_DATA, index, 0, NULL,
Packit 34410b
						read_oob_data_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	} else if (use_le && provide_p256) {
Packit 34410b
		uint8_t type = (1 << BDADDR_LE_PUBLIC) |
Packit 34410b
						(1 << BDADDR_LE_RANDOM);
Packit 34410b
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, index,
Packit 34410b
						sizeof(type), &type,
Packit 34410b
						read_oob_ext_data_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	} else if (use_le && provide_tk) {
Packit 34410b
		const uint8_t *tk = oob_tk;
Packit 34410b
Packit 34410b
		if (index == index1)
Packit 34410b
			add_remote_oob_data(index2, &bdaddr1,
Packit 34410b
						tk, NULL, NULL, NULL);
Packit 34410b
		else if (index == index2)
Packit 34410b
			add_remote_oob_data(index1, &bdaddr2,
Packit 34410b
						tk, NULL, NULL, NULL);
Packit 34410b
	} else {
Packit 34410b
		if (index == index1)
Packit 34410b
			add_remote_oob_data(index2, &bdaddr1,
Packit 34410b
						NULL, NULL, NULL, NULL);
Packit 34410b
		else if (index == index2)
Packit 34410b
			add_remote_oob_data(index1, &bdaddr2,
Packit 34410b
						NULL, NULL, NULL, NULL);
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void clear_link_keys(uint16_t index)
Packit 34410b
{
Packit 34410b
	struct mgmt_cp_load_link_keys cp;
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	cp.debug_keys = 0x00;
Packit 34410b
	cp.key_count = cpu_to_le16(0);
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_LOAD_LINK_KEYS, index,
Packit 34410b
					sizeof(cp), &cp, NULL, NULL, NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void clear_long_term_keys(uint16_t index)
Packit 34410b
{
Packit 34410b
	struct mgmt_cp_load_long_term_keys cp;
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	cp.key_count = cpu_to_le16(0);
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_LOAD_LONG_TERM_KEYS, index,
Packit 34410b
					sizeof(cp), &cp, NULL, NULL, NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void clear_identity_resolving_keys(uint16_t index)
Packit 34410b
{
Packit 34410b
	struct mgmt_cp_load_irks cp;
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	cp.irk_count = cpu_to_le16(0);
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_LOAD_IRKS, index,
Packit 34410b
					sizeof(cp), &cp, NULL, NULL, NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void clear_remote_oob_data(uint16_t index)
Packit 34410b
{
Packit 34410b
	struct mgmt_cp_remove_remote_oob_data cp;
Packit 34410b
Packit 34410b
	memset(&cp, 0, sizeof(cp));
Packit 34410b
	bacpy(&cp.addr.bdaddr, BDADDR_ANY);
Packit 34410b
	cp.addr.type = BDADDR_BREDR;
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_REMOVE_REMOTE_OOB_DATA, index,
Packit 34410b
					sizeof(cp), &cp, NULL, NULL, NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_powered_down_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Power down for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_bredr_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Setting BR/EDR for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_le_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Setting LE for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_ssp_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Simple Pairing for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_static_address_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Static address for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_secure_conn_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Secure connections for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_privacy_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Setting privacy for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_debug_keys_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Setting debug keys for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void set_bondable_complete(uint8_t status, uint16_t len,
Packit 34410b
					const void *param, void *user_data)
Packit 34410b
{
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Setting bondable for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void read_info(uint8_t status, uint16_t len, const void *param,
Packit 34410b
							void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_rp_read_info *rp = param;
Packit 34410b
	uint16_t index = PTR_TO_UINT(user_data);
Packit 34410b
	uint32_t supported_settings;
Packit 34410b
	uint8_t val;
Packit 34410b
	char str[18];
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Reading info for index %u failed: %s\n",
Packit 34410b
						index, mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	ba2str(&rp->bdaddr, str);
Packit 34410b
Packit 34410b
	printf("[Index %u]\n", index);
Packit 34410b
	printf("  Address: %s\n", str);
Packit 34410b
Packit 34410b
	if (index == index1)
Packit 34410b
		bacpy(&bdaddr1, &rp->bdaddr);
Packit 34410b
	else if (index == index2)
Packit 34410b
		bacpy(&bdaddr2, &rp->bdaddr);
Packit 34410b
Packit 34410b
	supported_settings = le32_to_cpu(rp->supported_settings);
Packit 34410b
Packit 34410b
	if (use_bredr && !(supported_settings & MGMT_SETTING_BREDR)) {
Packit 34410b
		fprintf(stderr, "BR/EDR support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (!use_legacy && !(supported_settings & MGMT_SETTING_SSP)) {
Packit 34410b
		fprintf(stderr, "Secure Simple Pairing support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_le && !(supported_settings & MGMT_SETTING_LE)) {
Packit 34410b
		fprintf(stderr, "Low Energy support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_sc && !(supported_settings & MGMT_SETTING_SECURE_CONN)) {
Packit 34410b
		fprintf(stderr, "Secure Connections support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_sconly && !(supported_settings & MGMT_SETTING_SECURE_CONN)) {
Packit 34410b
		fprintf(stderr, "Secure Connections Only support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_privacy && !(supported_settings & MGMT_SETTING_PRIVACY)) {
Packit 34410b
		fprintf(stderr, "Privacy support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_debug && !(supported_settings & MGMT_SETTING_DEBUG_KEYS)) {
Packit 34410b
		fprintf(stderr, "Debug keys support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_cross && (!(supported_settings & MGMT_SETTING_BREDR) ||
Packit 34410b
				!(supported_settings & MGMT_SETTING_LE))) {
Packit 34410b
		fprintf(stderr, "Dual-mode support is support missing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (provide_tk) {
Packit 34410b
		const uint8_t *tk = oob_tk;
Packit 34410b
		int i;
Packit 34410b
Packit 34410b
		printf("  TK Value: ");
Packit 34410b
		for (i = 0; i < 16; i++)
Packit 34410b
			printf("%02x", tk[i]);
Packit 34410b
		printf("\n");
Packit 34410b
	}
Packit 34410b
Packit 34410b
	mgmt_register(mgmt, MGMT_EV_PIN_CODE_REQUEST, index,
Packit 34410b
						pin_code_request_event,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
	mgmt_register(mgmt, MGMT_EV_NEW_LINK_KEY, index,
Packit 34410b
						new_link_key_event,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
	mgmt_register(mgmt, MGMT_EV_NEW_LONG_TERM_KEY, index,
Packit 34410b
						new_long_term_key_event,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
	val = 0x00;
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_SET_POWERED, index, 1, &val,
Packit 34410b
						set_powered_down_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
	clear_link_keys(index);
Packit 34410b
	clear_long_term_keys(index);
Packit 34410b
	clear_identity_resolving_keys(index);
Packit 34410b
	clear_remote_oob_data(index);
Packit 34410b
Packit 34410b
	if (use_bredr) {
Packit 34410b
		val = 0x01;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_BREDR, index, 1, &val,
Packit 34410b
						set_bredr_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
		val = use_cross ? 0x01 : 0x00;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_LE, index, 1, &val,
Packit 34410b
						set_le_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
		val = use_legacy ? 0x00 : 0x01;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_SSP, index, 1, &val,
Packit 34410b
						set_ssp_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	} else if (use_le) {
Packit 34410b
		val = 0x01;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_LE, index, 1, &val,
Packit 34410b
						set_le_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
		val = use_cross ? 0x01 : 0x00;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_BREDR, index, 1, &val,
Packit 34410b
						set_bredr_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
		if (use_cross) {
Packit 34410b
			val = use_legacy ? 0x00 : 0x01;
Packit 34410b
			mgmt_send(mgmt, MGMT_OP_SET_SSP, index, 1, &val,
Packit 34410b
						set_ssp_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
		}
Packit 34410b
	} else {
Packit 34410b
		fprintf(stderr, "Invalid transport for pairing\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_random) {
Packit 34410b
		bdaddr_t bdaddr;
Packit 34410b
Packit 34410b
		str2ba("c0:00:aa:bb:00:00", &bdaddr);
Packit 34410b
		bdaddr.b[0] = index;
Packit 34410b
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_STATIC_ADDRESS, index, 6, &bdaddr,
Packit 34410b
						set_static_address_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
		if (index == index1)
Packit 34410b
			bacpy(&bdaddr1, &bdaddr);
Packit 34410b
		else if (index == index2)
Packit 34410b
			bacpy(&bdaddr2, &bdaddr);
Packit 34410b
	} else {
Packit 34410b
		bdaddr_t bdaddr;
Packit 34410b
Packit 34410b
		bacpy(&bdaddr, BDADDR_ANY);
Packit 34410b
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_STATIC_ADDRESS, index, 6, &bdaddr,
Packit 34410b
						set_static_address_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_sc) {
Packit 34410b
		val = 0x01;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_SECURE_CONN, index, 1, &val,
Packit 34410b
						set_secure_conn_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	} else if (use_sconly) {
Packit 34410b
		val = 0x02;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_SECURE_CONN, index, 1, &val,
Packit 34410b
						set_secure_conn_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	} else {
Packit 34410b
		val = 0x00;
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_SECURE_CONN, index, 1, &val,
Packit 34410b
						set_secure_conn_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_privacy) {
Packit 34410b
		struct mgmt_cp_set_privacy cp;
Packit 34410b
Packit 34410b
		if (index == index2) {
Packit 34410b
			cp.privacy = 0x01;
Packit 34410b
			memcpy(cp.irk, REMOTE_IRK, sizeof(cp.irk));
Packit 34410b
		} else {
Packit 34410b
			cp.privacy = 0x00;
Packit 34410b
			memset(cp.irk, 0, sizeof(cp.irk));
Packit 34410b
		}
Packit 34410b
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_PRIVACY, index, sizeof(cp), &cp,
Packit 34410b
						set_privacy_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	} else {
Packit 34410b
		struct mgmt_cp_set_privacy cp;
Packit 34410b
Packit 34410b
		cp.privacy = 0x00;
Packit 34410b
		memset(cp.irk, 0, sizeof(cp.irk));
Packit 34410b
Packit 34410b
		mgmt_send(mgmt, MGMT_OP_SET_PRIVACY, index, sizeof(cp), &cp,
Packit 34410b
						set_privacy_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
	}
Packit 34410b
Packit 34410b
	val = 0x00;
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_SET_DEBUG_KEYS, index, 1, &val,
Packit 34410b
						set_debug_keys_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
	val = 0x01;
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_SET_BONDABLE, index, 1, &val,
Packit 34410b
						set_bondable_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
Packit 34410b
	val = 0x01;
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_SET_POWERED, index, 1, &val,
Packit 34410b
						set_powered_complete,
Packit 34410b
						UINT_TO_PTR(index), NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void read_index_list(uint8_t status, uint16_t len, const void *param,
Packit 34410b
							void *user_data)
Packit 34410b
{
Packit 34410b
	const struct mgmt_rp_read_index_list *rp = param;
Packit 34410b
	uint16_t count;
Packit 34410b
	int i;
Packit 34410b
Packit 34410b
	if (status) {
Packit 34410b
		fprintf(stderr, "Reading index list failed: %s\n",
Packit 34410b
						mgmt_errstr(status));
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	count = le16_to_cpu(rp->num_controllers);
Packit 34410b
Packit 34410b
	if (count < 2) {
Packit 34410b
		fprintf(stderr, "At least 2 controllers are required\n");
Packit 34410b
		mainloop_quit();
Packit 34410b
		return;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	for (i = 0; i < count; i++) {
Packit 34410b
		uint16_t index = cpu_to_le16(rp->index[i]);
Packit 34410b
Packit 34410b
		if (index < index1)
Packit 34410b
			index1 = index;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	for (i = 0; i < count; i++) {
Packit 34410b
		uint16_t index = cpu_to_le16(rp->index[i]);
Packit 34410b
Packit 34410b
		if (index < index2 && index > index1)
Packit 34410b
			index2 = index;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	printf("Selecting index %u for initiator\n", index1);
Packit 34410b
	printf("Selecting index %u for acceptor\n", index2);
Packit 34410b
Packit 34410b
	if (provide_tk) {
Packit 34410b
		struct bt_crypto *crypto;
Packit 34410b
Packit 34410b
		printf("Generating Security Manager TK Value\n");
Packit 34410b
Packit 34410b
		crypto = bt_crypto_new();
Packit 34410b
		bt_crypto_random_bytes(crypto, oob_tk, 16);
Packit 34410b
		bt_crypto_unref(crypto);
Packit 34410b
	}
Packit 34410b
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_READ_INFO, index1, 0, NULL,
Packit 34410b
				read_info, UINT_TO_PTR(index1), NULL);
Packit 34410b
	mgmt_send(mgmt, MGMT_OP_READ_INFO, index2, 0, NULL,
Packit 34410b
				read_info, UINT_TO_PTR(index2), NULL);
Packit 34410b
}
Packit 34410b
Packit 34410b
static void signal_callback(int signum, void *user_data)
Packit 34410b
{
Packit 34410b
	switch (signum) {
Packit 34410b
	case SIGINT:
Packit 34410b
	case SIGTERM:
Packit 34410b
		mainloop_quit();
Packit 34410b
		break;
Packit 34410b
	}
Packit 34410b
}
Packit 34410b
Packit 34410b
static void usage(void)
Packit 34410b
{
Packit 34410b
	printf("oobtest - Out-of-band pairing testing\n"
Packit 34410b
		"Usage:\n");
Packit 34410b
	printf("\toobtest [options]\n");
Packit 34410b
	printf("options:\n"
Packit 34410b
		"\t-B, --bredr            Use BR/EDR transport\n"
Packit 34410b
		"\t-L, --le               Use LE transport\n"
Packit 34410b
		"\t-S, --sc               Use Secure Connections\n"
Packit 34410b
		"\t-O, --sconly           Use Secure Connections Only\n"
Packit 34410b
		"\t-P, --legacy           Use Legacy Pairing\n"
Packit 34410b
		"\t-R, --random           Use Static random address\n"
Packit 34410b
		"\t-Y, --privacy          Use LE privacy feature\n"
Packit 34410b
		"\t-D, --debug            Use Pairing debug keys\n"
Packit 34410b
		"\t-C, --cross            Use cross-transport pairing\n"
Packit 34410b
		"\t-0, --tk               Provide LE legacy OOB data\n"
Packit 34410b
		"\t-1, --p192             Provide P-192 OOB data\n"
Packit 34410b
		"\t-2, --p256             Provide P-256 OOB data\n"
Packit 34410b
		"\t-I, --initiator        Initiator provides OOB data\n"
Packit 34410b
		"\t-A, --acceptor         Acceptor provides OOB data\n"
Packit 34410b
		"\t-h, --help             Show help options\n");
Packit 34410b
}
Packit 34410b
Packit 34410b
static const struct option main_options[] = {
Packit 34410b
	{ "bredr",     no_argument,       NULL, 'B' },
Packit 34410b
	{ "le",        no_argument,       NULL, 'L' },
Packit 34410b
	{ "sc",        no_argument,       NULL, 'S' },
Packit 34410b
	{ "sconly",    no_argument,       NULL, 'O' },
Packit 34410b
	{ "legacy",    no_argument,       NULL, 'P' },
Packit 34410b
	{ "random",    no_argument,       NULL, 'R' },
Packit 34410b
	{ "static",    no_argument,       NULL, 'R' },
Packit 34410b
	{ "privacy",   no_argument,       NULL, 'Y' },
Packit 34410b
	{ "debug",     no_argument,       NULL, 'D' },
Packit 34410b
	{ "cross",     no_argument,       NULL, 'C' },
Packit 34410b
	{ "dual",      no_argument,       NULL, 'C' },
Packit 34410b
	{ "tk",        no_argument,       NULL, '0' },
Packit 34410b
	{ "p192",      no_argument,       NULL, '1' },
Packit 34410b
	{ "p256",      no_argument,       NULL, '2' },
Packit 34410b
	{ "initiator", no_argument,       NULL, 'I' },
Packit 34410b
	{ "acceptor",  no_argument,       NULL, 'A' },
Packit 34410b
	{ "version",   no_argument,       NULL, 'v' },
Packit 34410b
	{ "help",      no_argument,       NULL, 'h' },
Packit 34410b
	{ }
Packit 34410b
};
Packit 34410b
Packit 34410b
int main(int argc ,char *argv[])
Packit 34410b
{
Packit 34410b
	int exit_status;
Packit 34410b
Packit 34410b
	for (;;) {
Packit 34410b
		int opt;
Packit 34410b
Packit 34410b
		opt = getopt_long(argc, argv, "BLSOPRYDC012IAvh",
Packit 34410b
						main_options, NULL);
Packit 34410b
		if (opt < 0)
Packit 34410b
			break;
Packit 34410b
Packit 34410b
		switch (opt) {
Packit 34410b
		case 'B':
Packit 34410b
			use_bredr = true;
Packit 34410b
			break;
Packit 34410b
		case 'L':
Packit 34410b
			use_le = true;
Packit 34410b
			break;
Packit 34410b
		case 'S':
Packit 34410b
			use_sc = true;
Packit 34410b
			break;
Packit 34410b
		case 'O':
Packit 34410b
			use_sconly = true;
Packit 34410b
			break;
Packit 34410b
		case 'P':
Packit 34410b
			use_legacy = true;
Packit 34410b
			break;
Packit 34410b
		case 'R':
Packit 34410b
			use_random = true;
Packit 34410b
			break;
Packit 34410b
		case 'Y':
Packit 34410b
			use_privacy = true;
Packit 34410b
			break;
Packit 34410b
		case 'D':
Packit 34410b
			use_debug = true;
Packit 34410b
			break;
Packit 34410b
		case 'C':
Packit 34410b
			use_cross = true;
Packit 34410b
			break;
Packit 34410b
		case '0':
Packit 34410b
			provide_tk = true;
Packit 34410b
			break;
Packit 34410b
		case '1':
Packit 34410b
			provide_p192 = true;
Packit 34410b
			break;
Packit 34410b
		case '2':
Packit 34410b
			provide_p256 = true;
Packit 34410b
			break;
Packit 34410b
		case 'I':
Packit 34410b
			provide_initiator = true;
Packit 34410b
			break;
Packit 34410b
		case 'A':
Packit 34410b
			provide_acceptor = true;
Packit 34410b
			break;
Packit 34410b
		case 'v':
Packit 34410b
			printf("%s\n", VERSION);
Packit 34410b
			return EXIT_SUCCESS;
Packit 34410b
		case 'h':
Packit 34410b
			usage();
Packit 34410b
			return EXIT_SUCCESS;
Packit 34410b
		default:
Packit 34410b
			return EXIT_FAILURE;
Packit 34410b
		}
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (argc - optind > 0) {
Packit 34410b
		fprintf(stderr, "Invalid command line parameters\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_bredr == use_le) {
Packit 34410b
		fprintf(stderr, "Specify either --bredr or --le\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_legacy && !use_bredr) {
Packit 34410b
		fprintf(stderr, "Specify --legacy with --bredr\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_privacy && !use_le && !use_cross ) {
Packit 34410b
		fprintf(stderr, "Specify --privacy with --le or --cross\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_random && !use_le) {
Packit 34410b
		fprintf(stderr, "Specify --random with --le\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_random && use_cross) {
Packit 34410b
		fprintf(stderr, "Only --random or --cross can be used\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (use_sc && use_sconly) {
Packit 34410b
		fprintf(stderr, "Only --sc or --sconly can be used\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	mainloop_init();
Packit 34410b
Packit 34410b
	mgmt = mgmt_new_default();
Packit 34410b
	if (!mgmt) {
Packit 34410b
		fprintf(stderr, "Failed to open management socket\n");
Packit 34410b
		return EXIT_FAILURE;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	if (!mgmt_send(mgmt, MGMT_OP_READ_INDEX_LIST,
Packit 34410b
					MGMT_INDEX_NONE, 0, NULL,
Packit 34410b
					read_index_list, NULL, NULL)) {
Packit 34410b
		fprintf(stderr, "Failed to read index list\n");
Packit 34410b
		exit_status = EXIT_FAILURE;
Packit 34410b
		goto done;
Packit 34410b
	}
Packit 34410b
Packit 34410b
	exit_status = mainloop_run_with_signal(signal_callback, NULL);
Packit 34410b
Packit 34410b
done:
Packit 34410b
	mgmt_unref(mgmt);
Packit 34410b
Packit 34410b
	return exit_status;
Packit 34410b
}