Skip to content

Commit ee79328

Browse files
Johan Hedbergnashif
authored andcommitted
Bluetooth: Mesh: Fix missing protocol error timeout
Provisioning errors shouldn't cause device to close link. Upon error, device will send Provisioning Failed PDU, and any further PDU's will be considered as unexpected as per Mesh Profile section 5.4.4. Also a timer is started every time device sends or receives a PDU. This affects MESH/NODE/PROV/BV-10-C test case. Signed-off-by: Johan Hedberg <[email protected]>
1 parent 8c2c561 commit ee79328

File tree

1 file changed

+71
-50
lines changed
  • subsys/bluetooth/host/mesh

1 file changed

+71
-50
lines changed

subsys/bluetooth/host/mesh/prov.c

Lines changed: 71 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ enum {
109109
SEND_CONFIRM, /* Waiting to send Confirm value */
110110
WAIT_NUMBER, /* Waiting for number input from user */
111111
WAIT_STRING, /* Waiting for string input from user */
112+
LINK_INVALID, /* Error occurred during provisioning */
112113

113114
NUM_FLAGS,
114115
};
@@ -160,6 +161,8 @@ struct prov_link {
160161
struct k_delayed_work retransmit;
161162
} tx;
162163
#endif
164+
165+
struct k_delayed_work prot_timer;
163166
};
164167

165168
struct prov_rx {
@@ -171,6 +174,7 @@ struct prov_rx {
171174
#define RETRANSMIT_TIMEOUT K_MSEC(500)
172175
#define BUF_TIMEOUT K_MSEC(400)
173176
#define TRANSACTION_TIMEOUT K_SECONDS(30)
177+
#define PROTOCOL_TIMEOUT K_SECONDS(60)
174178

175179
#if defined(CONFIG_BT_MESH_PB_GATT)
176180
#define PROV_BUF_HEADROOM 5
@@ -186,10 +190,10 @@ static struct prov_link link;
186190

187191
static const struct bt_mesh_prov *prov;
188192

189-
static void close_link(u8_t err, u8_t reason);
190-
191193
static void reset_state(void)
192194
{
195+
k_delayed_work_cancel(&link.prot_timer);
196+
193197
/* Disable Attention Timer if it was set */
194198
if (link.conf_inputs[0]) {
195199
bt_mesh_attention(NULL, 0);
@@ -202,7 +206,9 @@ static void reset_state(void)
202206
#endif
203207

204208
#if defined(CONFIG_BT_MESH_PB_ADV)
205-
/* Clear everything except the retransmit delayed work config */
209+
/* Clear everything except the retransmit and protocol timer
210+
* delayed work objects.
211+
*/
206212
(void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
207213
link.rx.prev_id = XACT_NVAL;
208214

@@ -213,8 +219,9 @@ static void reset_state(void)
213219
link.rx.buf = &rx_buf;
214220
#endif /* PB_GATT */
215221

216-
#else
217-
(void)memset(&link, 0, sizeof(link));
222+
#else /* !PB_ADV */
223+
/* Clear everything except the protocol timer (k_delayed_work) */
224+
(void)memset(&link, 0, offsetof(struct prov_link, prot_timer));
218225
#endif /* PB_ADV */
219226
}
220227

@@ -471,6 +478,8 @@ static int prov_send_gatt(struct net_buf_simple *msg)
471478

472479
static inline int prov_send(struct net_buf_simple *buf)
473480
{
481+
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
482+
474483
#if defined(CONFIG_BT_MESH_PB_GATT)
475484
if (link.conn) {
476485
return prov_send_gatt(buf);
@@ -496,6 +505,8 @@ static void prov_send_fail_msg(u8_t err)
496505
prov_buf_init(&buf, PROV_FAILED);
497506
net_buf_simple_add_u8(&buf, err);
498507
prov_send(&buf);
508+
509+
atomic_set_bit(link.flags, LINK_INVALID);
499510
}
500511

501512
static void prov_invite(const u8_t *data)
@@ -540,7 +551,7 @@ static void prov_invite(const u8_t *data)
540551

541552
if (prov_send(&buf)) {
542553
BT_ERR("Failed to send capabilities");
543-
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
554+
prov_send_fail_msg(PROV_ERR_RESOURCES);
544555
return;
545556
}
546557

@@ -746,23 +757,23 @@ static void send_confirm(void)
746757

747758
if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
748759
BT_ERR("Unable to generate confirmation salt");
749-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
760+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
750761
return;
751762
}
752763

753764
BT_DBG("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16));
754765

755766
if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
756767
BT_ERR("Unable to generate confirmation key");
757-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
768+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
758769
return;
759770
}
760771

761772
BT_DBG("ConfirmationKey: %s", bt_hex(link.conf_key, 16));
762773

763774
if (bt_rand(link.rand, 16)) {
764775
BT_ERR("Unable to generate random number");
765-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
776+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
766777
return;
767778
}
768779

@@ -773,13 +784,13 @@ static void send_confirm(void)
773784
if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,
774785
net_buf_simple_add(&cfm, 16))) {
775786
BT_ERR("Unable to generate confirmation value");
776-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
787+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
777788
return;
778789
}
779790

780791
if (prov_send(&cfm)) {
781792
BT_ERR("Failed to send Provisioning Confirm");
782-
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
793+
prov_send_fail_msg(PROV_ERR_RESOURCES);
783794
return;
784795
}
785796

@@ -846,7 +857,7 @@ static void prov_dh_key_cb(const u8_t key[32])
846857

847858
if (!key) {
848859
BT_ERR("DHKey generation failed");
849-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
860+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
850861
return;
851862
}
852863

@@ -874,7 +885,7 @@ static void send_pub_key(void)
874885
key = bt_pub_key_get();
875886
if (!key) {
876887
BT_ERR("No public key available");
877-
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
888+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
878889
return;
879890
}
880891

@@ -899,7 +910,7 @@ static void send_pub_key(void)
899910

900911
if (bt_dh_key_gen(buf.data, prov_dh_key_cb)) {
901912
BT_ERR("Failed to generate DHKey");
902-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
913+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
903914
return;
904915
}
905916

@@ -969,15 +980,15 @@ static void prov_random(const u8_t *data)
969980

970981
if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
971982
BT_ERR("Unable to calculate confirmation verification");
972-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
983+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
973984
return;
974985
}
975986

976987
if (memcmp(conf_verify, link.conf, 16)) {
977988
BT_ERR("Invalid confirmation value");
978989
BT_DBG("Received: %s", bt_hex(link.conf, 16));
979990
BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
980-
close_link(PROV_ERR_CFM_FAILED, CLOSE_REASON_FAILED);
991+
prov_send_fail_msg(PROV_ERR_CFM_FAILED);
981992
return;
982993
}
983994

@@ -986,14 +997,14 @@ static void prov_random(const u8_t *data)
986997

987998
if (prov_send(&rnd)) {
988999
BT_ERR("Failed to send Provisioning Random");
989-
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
1000+
prov_send_fail_msg(PROV_ERR_RESOURCES);
9901001
return;
9911002
}
9921003

9931004
if (bt_mesh_prov_salt(link.conf_salt, data, link.rand,
9941005
link.prov_salt)) {
9951006
BT_ERR("Failed to generate provisioning salt");
996-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
1007+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
9971008
return;
9981009
}
9991010

@@ -1030,7 +1041,7 @@ static void prov_data(const u8_t *data)
10301041
err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
10311042
if (err) {
10321043
BT_ERR("Unable to generate session key");
1033-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
1044+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
10341045
return;
10351046
}
10361047

@@ -1039,7 +1050,7 @@ static void prov_data(const u8_t *data)
10391050
err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
10401051
if (err) {
10411052
BT_ERR("Unable to generate session nonce");
1042-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
1053+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
10431054
return;
10441055
}
10451056

@@ -1048,14 +1059,14 @@ static void prov_data(const u8_t *data)
10481059
err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
10491060
if (err) {
10501061
BT_ERR("Unable to decrypt provisioning data");
1051-
close_link(PROV_ERR_DECRYPT, CLOSE_REASON_FAILED);
1062+
prov_send_fail_msg(PROV_ERR_DECRYPT);
10521063
return;
10531064
}
10541065

10551066
err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key);
10561067
if (err) {
10571068
BT_ERR("Unable to generate device key");
1058-
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
1069+
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
10591070
return;
10601071
}
10611072

@@ -1122,27 +1133,6 @@ static const struct {
11221133
{ prov_failed, 1 },
11231134
};
11241135

1125-
static void close_link(u8_t err, u8_t reason)
1126-
{
1127-
#if defined(CONFIG_BT_MESH_PB_GATT)
1128-
if (link.conn) {
1129-
bt_mesh_pb_gatt_close(link.conn);
1130-
return;
1131-
}
1132-
#endif
1133-
1134-
#if defined(CONFIG_BT_MESH_PB_ADV)
1135-
if (err) {
1136-
prov_send_fail_msg(err);
1137-
}
1138-
1139-
link.rx.seg = 0U;
1140-
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
1141-
#endif
1142-
1143-
reset_state();
1144-
}
1145-
11461136
#if defined(CONFIG_BT_MESH_PB_ADV)
11471137
static void prov_retransmit(struct k_work *work)
11481138
{
@@ -1273,6 +1263,8 @@ static void prov_msg_recv(void)
12731263

12741264
BT_DBG("type 0x%02x len %u", type, link.rx.buf->len);
12751265

1266+
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
1267+
12761268
if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
12771269
BT_ERR("Incorrect FCS");
12781270
return;
@@ -1282,6 +1274,12 @@ static void prov_msg_recv(void)
12821274
link.rx.prev_id = link.rx.id;
12831275
link.rx.id = 0U;
12841276

1277+
if (atomic_test_bit(link.flags, LINK_INVALID)) {
1278+
BT_WARN("Unexpected msg 0x%02x on invalidated link", type);
1279+
prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
1280+
return;
1281+
}
1282+
12851283
if (type != PROV_FAILED && type != link.expect) {
12861284
BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
12871285
prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
@@ -1290,14 +1288,14 @@ static void prov_msg_recv(void)
12901288

12911289
if (type >= ARRAY_SIZE(prov_handlers)) {
12921290
BT_ERR("Unknown provisioning PDU type 0x%02x", type);
1293-
close_link(PROV_ERR_NVAL_PDU, CLOSE_REASON_FAILED);
1291+
prov_send_fail_msg(PROV_ERR_NVAL_PDU);
12941292
return;
12951293
}
12961294

12971295
if (1 + prov_handlers[type].len != link.rx.buf->len) {
12981296
BT_ERR("Invalid length %u for type 0x%02x",
12991297
link.rx.buf->len, type);
1300-
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
1298+
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
13011299
return;
13021300
}
13031301

@@ -1324,7 +1322,7 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
13241322

13251323
if (seg > link.rx.last_seg) {
13261324
BT_ERR("Invalid segment index %u", seg);
1327-
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
1325+
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
13281326
return;
13291327
} else if (seg == link.rx.last_seg) {
13301328
u8_t expect_len;
@@ -1334,7 +1332,7 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
13341332
if (expect_len != buf->len) {
13351333
BT_ERR("Incorrect last seg len: %u != %u",
13361334
expect_len, buf->len);
1337-
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
1335+
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
13381336
return;
13391337
}
13401338
}
@@ -1387,20 +1385,20 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
13871385

13881386
if (link.rx.buf->len < 1) {
13891387
BT_ERR("Ignoring zero-length provisioning PDU");
1390-
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
1388+
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
13911389
return;
13921390
}
13931391

13941392
if (link.rx.buf->len > link.rx.buf->size) {
13951393
BT_ERR("Too large provisioning PDU (%u bytes)",
13961394
link.rx.buf->len);
1397-
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
1395+
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
13981396
return;
13991397
}
14001398

14011399
if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->len <= 20U) {
14021400
BT_ERR("Too small total length for multi-segment PDU");
1403-
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
1401+
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
14041402
return;
14051403
}
14061404

@@ -1556,6 +1554,27 @@ bool bt_prov_active(void)
15561554
return atomic_test_bit(link.flags, LINK_ACTIVE);
15571555
}
15581556

1557+
static void protocol_timeout(struct k_work *work)
1558+
{
1559+
BT_DBG("Protocol timeout");
1560+
1561+
#if defined(CONFIG_BT_MESH_PB_GATT)
1562+
if (link.conn) {
1563+
bt_mesh_pb_gatt_close(link.conn);
1564+
return;
1565+
}
1566+
#endif
1567+
1568+
#if defined(CONFIG_BT_MESH_PB_ADV)
1569+
u8_t reason = CLOSE_REASON_TIMEOUT;
1570+
1571+
link.rx.seg = 0U;
1572+
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
1573+
1574+
reset_state();
1575+
#endif
1576+
}
1577+
15591578
int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
15601579
{
15611580
static struct bt_pub_key_cb pub_key_cb = {
@@ -1568,6 +1587,8 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
15681587
return -EINVAL;
15691588
}
15701589

1590+
k_delayed_work_init(&link.prot_timer, protocol_timeout);
1591+
15711592
err = bt_pub_key_gen(&pub_key_cb);
15721593
if (err) {
15731594
BT_ERR("Failed to generate public key (%d)", err);

0 commit comments

Comments
 (0)