Commit 6a9243c1 authored by Szymon Janc's avatar Szymon Janc Committed by Carles Cufi
Browse files

Bluetooth: Controller: LLCP: Fix handling of invalid DLE parameters

If peer sents invalid value in DLE request or response just ignore
those and keep using old values when calculating effective DLE.

This was affecting following qualification test cases:
LL/CON/PER/BI-10-C
LL/CON/PER/BI-11-C
LL/CON/PER/BI-12-C
LL/CON/CEN/BI-07-C
LL/CON/CEN/BI-08-C
LL/CON/CEN/BI-09-C

Signed-off-by: default avatarSzymon Janc <szymon.janc@codecoup.pl>
parent 2d824f48
Loading
Loading
Loading
Loading
+11 −0
Changes for subsys/bluetooth/controller/ll_sw/pdu.h: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -81,6 +81,17 @@
#define PDU_DC_PAYLOAD_TIME_MIN 328
#define PDU_DC_PAYLOAD_TIME_MIN_CODED 2704

/* Data channel maximum payload size and time */
#define PDU_DC_PAYLOAD_SIZE_MAX 251

#if defined(CONFIG_BT_CTLR_DF)
#define PDU_DC_PAYLOAD_TIME_MAX 2128
#else
#define PDU_DC_PAYLOAD_TIME_MAX 2120
#endif

#define PDU_DC_PAYLOAD_TIME_MAX_CODED 17040

/* Link Layer header size of Data PDU. Assumes pdu_data is packed */
#define PDU_DC_LL_HEADER_SIZE  (offsetof(struct pdu_data, lldata))

+59 −8
Changes for subsys/bluetooth/controller/ll_sw/ull_llcp_pdu.c: 59 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -694,24 +694,75 @@ void llcp_ntf_encode_length_change(struct ll_conn *conn, struct pdu_data *pdu)
	p->max_tx_time = sys_cpu_to_le16(conn->lll.dle.eff.max_tx_time);
}

static bool dle_remote_valid(const struct data_pdu_length *remote)
{
	if (!IN_RANGE(remote->max_rx_octets, PDU_DC_PAYLOAD_SIZE_MIN,
		      PDU_DC_PAYLOAD_SIZE_MAX)) {
		return false;
	}

	if (!IN_RANGE(remote->max_tx_octets, PDU_DC_PAYLOAD_SIZE_MIN,
		      PDU_DC_PAYLOAD_SIZE_MAX)) {
		return false;
	}

#if defined(CONFIG_BT_CTLR_PHY)
	if (!IN_RANGE(remote->max_rx_time, PDU_DC_PAYLOAD_TIME_MIN,
		      PDU_DC_PAYLOAD_TIME_MAX_CODED)) {
		return false;
	}

	if (!IN_RANGE(remote->max_tx_time, PDU_DC_PAYLOAD_TIME_MIN,
		      PDU_DC_PAYLOAD_TIME_MAX_CODED)) {
		return false;
	}
#else
	if (!IN_RANGE(remote->max_rx_time, PDU_DC_PAYLOAD_TIME_MIN,
		      PDU_DC_PAYLOAD_TIME_MAX)) {
		return false;
	}

	if (!IN_RANGE(remote->max_tx_time, PDU_DC_PAYLOAD_TIME_MIN,
		      PDU_DC_PAYLOAD_TIME_MAX)) {
		return false;
	}
#endif /* CONFIG_BT_CTLR_PHY */

	return true;
}

void llcp_pdu_decode_length_req(struct ll_conn *conn, struct pdu_data *pdu)
{
	struct pdu_data_llctrl_length_req *p = &pdu->llctrl.length_req;
	struct data_pdu_length remote;

	remote.max_rx_octets = sys_le16_to_cpu(p->max_rx_octets);
	remote.max_tx_octets = sys_le16_to_cpu(p->max_tx_octets);
	remote.max_rx_time = sys_le16_to_cpu(p->max_rx_time);
	remote.max_tx_time = sys_le16_to_cpu(p->max_tx_time);

	conn->lll.dle.remote.max_rx_octets = sys_le16_to_cpu(p->max_rx_octets);
	conn->lll.dle.remote.max_tx_octets = sys_le16_to_cpu(p->max_tx_octets);
	conn->lll.dle.remote.max_rx_time = sys_le16_to_cpu(p->max_rx_time);
	conn->lll.dle.remote.max_tx_time = sys_le16_to_cpu(p->max_tx_time);
	if (!dle_remote_valid(&remote)) {
		return;
	}

	conn->lll.dle.remote = remote;
}

void llcp_pdu_decode_length_rsp(struct ll_conn *conn, struct pdu_data *pdu)
{
	struct pdu_data_llctrl_length_rsp *p = &pdu->llctrl.length_rsp;
	struct data_pdu_length remote;

	remote.max_rx_octets = sys_le16_to_cpu(p->max_rx_octets);
	remote.max_tx_octets = sys_le16_to_cpu(p->max_tx_octets);
	remote.max_rx_time = sys_le16_to_cpu(p->max_rx_time);
	remote.max_tx_time = sys_le16_to_cpu(p->max_tx_time);

	if (!dle_remote_valid(&remote)) {
		return;
	}

	conn->lll.dle.remote.max_rx_octets = sys_le16_to_cpu(p->max_rx_octets);
	conn->lll.dle.remote.max_tx_octets = sys_le16_to_cpu(p->max_tx_octets);
	conn->lll.dle.remote.max_rx_time = sys_le16_to_cpu(p->max_rx_time);
	conn->lll.dle.remote.max_tx_time = sys_le16_to_cpu(p->max_tx_time);
	conn->lll.dle.remote = remote;
}
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */