Пример #1
0
static void smp_new_conn(uint16_t handle, void *user_data)
{
	struct test_data *data = user_data;
	const struct smp_data *smp = data->test_data;
	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
	const struct smp_req_rsp *req;
	const void *pdu;

	tester_print("New SMP client connection with handle 0x%04x", handle);

	data->handle = handle;

	bthost_add_cid_hook(bthost, handle, SMP_CID, smp_server, data);

	if (smp->req_count == data->counter)
		return;

	req = &smp->req[data->counter];

	if (!req->send)
		return;

	tester_print("Sending SMP PDU");

	pdu = get_pdu(req->send);
	bthost_send_cid(bthost, handle, SMP_CID, pdu, req->send_len);

	if (!req->expect)
		test_condition_complete(data);
}
Пример #2
0
static void smp_server(const void *data, uint16_t len, void *user_data)
{
	struct test_data *test_data = user_data;
	struct bthost *bthost = hciemu_client_get_host(test_data->hciemu);
	const struct smp_data *smp = test_data->test_data;
	const struct smp_req_rsp *req;
	const void *pdu;
	uint8_t opcode;

	if (len < 1) {
		tester_warn("Received too small SMP PDU");
		goto failed;
	}

	opcode = *((const uint8_t *) data);

	tester_print("Received SMP opcode 0x%02x", opcode);

	if (test_data->counter >= smp->req_count) {
		test_condition_complete(test_data);
		return;
	}

	req = &smp->req[test_data->counter++];
	if (!req->expect)
		goto next;

	if (req->expect_len != len) {
		tester_warn("Unexpected SMP PDU length (%u != %u)",
							len, req->expect_len);
		goto failed;
	}

	switch (opcode) {
	case 0x01: /* Pairing Request */
		memcpy(test_data->preq, data, sizeof(test_data->preq));
		break;
	case 0x02: /* Pairing Response */
		memcpy(test_data->prsp, data, sizeof(test_data->prsp));
		break;
	case 0x03: /* Pairing Confirm */
		memcpy(test_data->pcnf, data + 1, 16);
		goto next;
	case 0x04: /* Pairing Random */
		memcpy(test_data->rrnd, data + 1, 16);
		if (!verify_random(data + 1))
			goto failed;
		goto next;
	default:
		break;
	}

	if (memcmp(req->expect, data, len) != 0) {
		tester_warn("Unexpected SMP PDU");
		goto failed;
	}

next:
	if (smp->req_count == test_data->counter) {
		test_condition_complete(test_data);
		return;
	}

	req = &smp->req[test_data->counter];

	pdu = get_pdu(req->send);
	bthost_send_cid(bthost, test_data->handle, SMP_CID, pdu,
							req->send_len);

	if (!req->expect)
		test_condition_complete(test_data);

	return;

failed:
	tester_test_failed();
}
Пример #3
0
void
test_send_pdu(struct proc *p, iscsi_test_send_pdu_parameters_t *par)
{
	static uint8_t pad_bytes[4] = { 0 };
	test_pars_t *tp;
	connection_t *conn;
	pdu_t *pdu;
	uint32_t psize = par->pdu_size;
	void *pdu_ptr = par->pdu_ptr;
	struct uio *uio;
	uint32_t i, pad, dsl, size;
	int s;

	if ((tp = find_test_id(par->test_id)) == NULL) {
		par->status = ISCSI_STATUS_INVALID_ID;
		return;
	}
	if (!psize || pdu_ptr == NULL ||
		((par->options & ISCSITEST_SFLAG_UPDATE_FIELDS) && psize < BHS_SIZE)) {
		par->status = ISCSI_STATUS_PARAMETER_INVALID;
		return;
	}
	if ((conn = tp->connection) == NULL) {
		par->status = ISCSI_STATUS_TEST_INACTIVE;
		return;
	}
	if ((pdu = get_pdu(conn, TRUE)) == NULL) {
		par->status = ISCSI_STATUS_TEST_CONNECTION_CLOSED;
		return;
	}
	DEB(1, ("Test Send PDU, id %d\n", par->test_id));

	if ((par->status = map_databuf(p, &pdu_ptr, psize)) != 0) {
		free_pdu(pdu);
		return;
	}

	i = 1;
	if (!par->options) {
		pdu->io_vec[0].iov_base = pdu_ptr;
		pdu->io_vec[0].iov_len = size = psize;
	} else {
		memcpy(&pdu->pdu, pdu_ptr, BHS_SIZE);

		if (!(pdu->pdu.Opcode & OP_IMMEDIATE))
			conn->session->CmdSN++;
		pdu->pdu.p.command.CmdSN = htonl(conn->session->CmdSN);

		dsl = psize - BHS_SIZE;
		size = BHS_SIZE;

		hton3(dsl, pdu->pdu.DataSegmentLength);

		if (conn->HeaderDigest &&
			!(par->options & ISCSITEST_SFLAG_NO_HEADER_DIGEST)) {
			pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);
			size += 4;
		}

		pdu->io_vec[0].iov_base = &pdu->pdu;
		pdu->io_vec[0].iov_len = size;

		if (dsl) {
			pdu->io_vec[1].iov_base = &pdu_ptr[BHS_SIZE];
			pdu->io_vec[1].iov_len = dsl;
			i++;
			size += dsl;

			/* Pad to next multiple of 4 */
			pad = (par->options & ISCSITEST_SFLAG_NO_PADDING) ? 0 : size & 0x03;

			if (pad) {
				pad = 4 - pad;
				pdu->io_vec[i].iov_base = pad_bytes;
				pdu->io_vec[i].iov_len = pad;
				i++;
				size += pad;
			}

			if (conn->DataDigest &&
				!(par->options & ISCSITEST_SFLAG_NO_DATA_DIGEST)) {
				pdu->data_digest = gen_digest_2(&pdu_ptr[BHS_SIZE], dsl,
												pad_bytes, pad);
				pdu->io_vec[i].iov_base = &pdu->data_digest;
				pdu->io_vec[i].iov_len = 4;
				i++;
				size += 4;
			}
		}
	}
	uio = &pdu->uio;
	uio->uio_iov = pdu->io_vec;
	UIO_SETUP_SYSSPACE(uio);
	uio->uio_rw = UIO_WRITE;
	uio->uio_iovcnt = i;
	uio->uio_resid = size;

	pdu->disp = PDUDISP_SIGNAL;
	pdu->flags = PDUF_BUSY | PDUF_NOUPDATE;

	s = splbio();
	/* Enqueue for sending */
	if (pdu->pdu.Opcode & OP_IMMEDIATE)
		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
	else
		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);

	wakeup(&conn->pdus_to_send);
	tsleep(pdu, PINOD, "test_send_pdu", 0);
	splx(s);

	unmap_databuf(p, pdu_ptr, psize);
	par->status = ISCSI_STATUS_SUCCESS;
	if (par->options & ISCSITEST_KILL_CONNECTION)
		kill_connection(conn, ISCSI_STATUS_TEST_CONNECTION_CLOSED, NO_LOGOUT,
						TRUE);
}