pb-adv.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <ell/ell.h>
  14. #include "mesh/mesh-defs.h"
  15. #include "mesh/crypto.h"
  16. #include "mesh/net.h"
  17. #include "mesh/mesh-io.h"
  18. #include "mesh/mesh.h"
  19. #include "mesh/prov.h"
  20. #include "mesh/provision.h"
  21. #include "mesh/pb-adv.h"
  22. struct pb_adv_session {
  23. mesh_prov_open_func_t open_cb;
  24. mesh_prov_close_func_t close_cb;
  25. mesh_prov_receive_func_t rx_cb;
  26. mesh_prov_ack_func_t ack_cb;
  27. struct l_timeout *tx_timeout;
  28. struct pb_adv_session *loop;
  29. uint32_t link_id;
  30. uint16_t exp_len;
  31. uint8_t exp_fcs;
  32. uint8_t exp_segs;
  33. uint8_t got_segs;
  34. uint8_t trans_num;
  35. uint8_t local_acked;
  36. uint8_t local_trans_num;
  37. uint8_t peer_trans_num;
  38. uint8_t last_peer_trans_num;
  39. uint8_t sar[80];
  40. uint8_t uuid[16];
  41. bool initiator;
  42. bool opened;
  43. void *user_data;
  44. };
  45. #define PB_ADV_ACK 0x01
  46. #define PB_ADV_OPEN_REQ 0x03
  47. #define PB_ADV_OPEN_CFM 0x07
  48. #define PB_ADV_CLOSE 0x0B
  49. #define PB_ADV_MTU 24
  50. struct pb_ack {
  51. uint8_t ad_type;
  52. uint32_t link_id;
  53. uint8_t trans_num;
  54. uint8_t opcode;
  55. } __packed;
  56. struct pb_open_req{
  57. uint8_t ad_type;
  58. uint32_t link_id;
  59. uint8_t trans_num;
  60. uint8_t opcode;
  61. uint8_t uuid[16];
  62. } __packed;
  63. struct pb_open_cfm{
  64. uint8_t ad_type;
  65. uint32_t link_id;
  66. uint8_t trans_num;
  67. uint8_t opcode;
  68. } __packed;
  69. struct pb_close_ind {
  70. uint8_t ad_type;
  71. uint32_t link_id;
  72. uint8_t trans_num;
  73. uint8_t opcode;
  74. uint8_t reason;
  75. } __packed;
  76. struct idle_rx {
  77. struct pb_adv_session *session;
  78. uint16_t len;
  79. uint8_t data[PB_ADV_MTU + 6];
  80. };
  81. static struct l_queue *pb_sessions = NULL;
  82. static const uint8_t filter[1] = { MESH_AD_TYPE_PROVISION };
  83. static void pb_adv_packet(void *user_data, const uint8_t *pkt, uint16_t len);
  84. static void idle_rx_adv(void *user_data)
  85. {
  86. struct idle_rx *rx = user_data;
  87. pb_adv_packet(rx->session, rx->data, rx->len);
  88. l_free(rx);
  89. }
  90. static void pb_adv_send(struct pb_adv_session *session,
  91. uint8_t count, uint16_t interval,
  92. void *data, uint16_t len)
  93. {
  94. struct idle_rx *rx;
  95. if (session->loop) {
  96. rx = l_new(struct idle_rx, 1);
  97. rx->session = session->loop;
  98. rx->len = len;
  99. memcpy(rx->data, data, len);
  100. l_idle_oneshot(idle_rx_adv, rx, NULL);
  101. } else
  102. mesh_send_pkt(count, interval, data, len);
  103. }
  104. static void send_adv_segs(struct pb_adv_session *session, const uint8_t *data,
  105. uint16_t size)
  106. {
  107. uint16_t init_size;
  108. uint8_t buf[PB_ADV_MTU + 6] = { MESH_AD_TYPE_PROVISION };
  109. uint8_t max_seg;
  110. uint8_t consumed;
  111. int i;
  112. if (!size)
  113. return;
  114. mesh_send_cancel(filter, sizeof(filter));
  115. l_put_be32(session->link_id, buf + 1);
  116. buf[1 + 4] = ++session->local_trans_num;
  117. if (size > PB_ADV_MTU - 4) {
  118. max_seg = 1 +
  119. (((size - (PB_ADV_MTU - 4)) - 1) / (PB_ADV_MTU - 1));
  120. init_size = PB_ADV_MTU - 4;
  121. } else {
  122. max_seg = 0;
  123. init_size = size;
  124. }
  125. l_debug("Sending %u fragments for %u octets", max_seg + 1, size);
  126. buf[6] = max_seg << 2;
  127. l_put_be16(size, buf + 7);
  128. buf[9] = mesh_crypto_compute_fcs(data, size);
  129. memcpy(buf + 10, data, init_size);
  130. l_debug("max_seg: %2.2x", max_seg);
  131. l_debug("size: %2.2x, CRC: %2.2x", size, buf[9]);
  132. pb_adv_send(session, MESH_IO_TX_COUNT_UNLIMITED, 200,
  133. buf, init_size + 10);
  134. consumed = init_size;
  135. for (i = 1; i <= max_seg; i++) {
  136. uint8_t seg_size; /* Amount of payload data being sent */
  137. if (size - consumed > PB_ADV_MTU - 1)
  138. seg_size = PB_ADV_MTU - 1;
  139. else
  140. seg_size = size - consumed;
  141. buf[6] = (i << 2) | 0x02;
  142. memcpy(buf + 7, data + consumed, seg_size);
  143. pb_adv_send(session, MESH_IO_TX_COUNT_UNLIMITED, 200,
  144. buf, seg_size + 7);
  145. consumed += seg_size;
  146. }
  147. }
  148. static bool session_match (const void *a, const void *b)
  149. {
  150. return a == b;
  151. }
  152. static bool uuid_match (const void *a, const void *b)
  153. {
  154. const struct pb_adv_session *session = a;
  155. const uint8_t *uuid = b;
  156. return !memcmp(session->uuid, uuid, sizeof(session->uuid));
  157. }
  158. static bool user_match (const void *a, const void *b)
  159. {
  160. const struct pb_adv_session *session = a;
  161. return session->user_data == b;
  162. }
  163. static void tx_timeout(struct l_timeout *timeout, void *user_data)
  164. {
  165. struct pb_adv_session *session = user_data;
  166. mesh_prov_close_func_t cb;
  167. if (!l_queue_find(pb_sessions, session_match, session))
  168. return;
  169. mesh_send_cancel(filter, sizeof(filter));
  170. l_debug("TX timeout");
  171. cb = session->close_cb;
  172. user_data = session->user_data;
  173. cb(user_data, 1);
  174. }
  175. static void pb_adv_tx(void *user_data, void *data, uint16_t len)
  176. {
  177. struct pb_adv_session *session = user_data;
  178. if (!l_queue_find(pb_sessions, session_match, session))
  179. return;
  180. l_timeout_remove(session->tx_timeout);
  181. session->tx_timeout = l_timeout_create(30, tx_timeout, session, NULL);
  182. send_adv_segs(session, data, len);
  183. }
  184. static void send_open_req(struct pb_adv_session *session)
  185. {
  186. struct pb_open_req open_req = { MESH_AD_TYPE_PROVISION };
  187. l_put_be32(session->link_id, &open_req.link_id);
  188. open_req.trans_num = 0;
  189. open_req.opcode = PB_ADV_OPEN_REQ;
  190. memcpy(open_req.uuid, session->uuid, 16);
  191. mesh_send_cancel(filter, sizeof(filter));
  192. pb_adv_send(session, MESH_IO_TX_COUNT_UNLIMITED, 500, &open_req,
  193. sizeof(open_req));
  194. }
  195. static void send_open_cfm(struct pb_adv_session *session)
  196. {
  197. struct pb_open_cfm open_cfm = { MESH_AD_TYPE_PROVISION };
  198. l_put_be32(session->link_id, &open_cfm.link_id);
  199. open_cfm.trans_num = 0;
  200. open_cfm.opcode = PB_ADV_OPEN_CFM;
  201. mesh_send_cancel(filter, sizeof(filter));
  202. pb_adv_send(session, MESH_IO_TX_COUNT_UNLIMITED, 500, &open_cfm,
  203. sizeof(open_cfm));
  204. }
  205. static void send_ack(struct pb_adv_session *session, uint8_t trans_num)
  206. {
  207. struct pb_ack ack = { MESH_AD_TYPE_PROVISION };
  208. if (!l_queue_find(pb_sessions, session_match, session))
  209. return;
  210. l_put_be32(session->link_id, &ack.link_id);
  211. ack.trans_num = trans_num;
  212. ack.opcode = PB_ADV_ACK;
  213. pb_adv_send(session, 1, 100, &ack, sizeof(ack));
  214. }
  215. static void send_close_ind(struct pb_adv_session *session, uint8_t reason)
  216. {
  217. struct pb_close_ind close_ind = { MESH_AD_TYPE_PROVISION };
  218. if (!l_queue_find(pb_sessions, session_match, session))
  219. return;
  220. l_put_be32(session->link_id, &close_ind.link_id);
  221. close_ind.trans_num = 0;
  222. close_ind.opcode = PB_ADV_CLOSE;
  223. close_ind.reason = reason;
  224. mesh_send_cancel(filter, sizeof(filter));
  225. pb_adv_send(session, 10, 100, &close_ind, sizeof(close_ind));
  226. }
  227. static void pb_adv_packet(void *user_data, const uint8_t *pkt, uint16_t len)
  228. {
  229. struct pb_adv_session *session = user_data;
  230. uint32_t link_id;
  231. size_t offset;
  232. uint8_t trans_num;
  233. uint8_t type;
  234. bool first;
  235. if (!l_queue_find(pb_sessions, session_match, session))
  236. return;
  237. link_id = l_get_be32(pkt + 1);
  238. type = l_get_u8(pkt + 6);
  239. /* Validate new or existing Connection ID */
  240. if (session->link_id) {
  241. if (session->link_id != link_id)
  242. return;
  243. } else if (type != 0x03)
  244. return;
  245. else if (!link_id)
  246. return;
  247. trans_num = l_get_u8(pkt + 5);
  248. pkt += 7;
  249. len -= 7;
  250. switch (type) {
  251. case PB_ADV_OPEN_CFM:
  252. /*
  253. * Ignore if:
  254. * 1. We are acceptor
  255. * 2. We are already provisioning on different link_id
  256. */
  257. if (!session->initiator)
  258. return;
  259. first = !session->opened;
  260. session->opened = true;
  261. /* Only call Open callback once */
  262. if (first) {
  263. l_debug("PB-ADV open confirmed");
  264. session->local_trans_num = 0xFF;
  265. session->open_cb(session->user_data, pb_adv_tx,
  266. session, PB_ADV);
  267. }
  268. return;
  269. case PB_ADV_OPEN_REQ:
  270. /*
  271. * Ignore if:
  272. * 1. We are initiator
  273. * 2. Open request not addressed to us
  274. * 3. We are already provisioning on different link_id
  275. */
  276. if (session->initiator)
  277. return;
  278. if (memcmp(pkt, session->uuid, 16))
  279. return;
  280. first = !session->link_id;
  281. session->link_id = link_id;
  282. session->last_peer_trans_num = 0xFF;
  283. session->peer_trans_num = 0x00;
  284. session->local_trans_num = 0x7F;
  285. session->opened = true;
  286. /* Only call Open callback once */
  287. if (first) {
  288. l_debug("PB-ADV open requested");
  289. session->open_cb(session->user_data, pb_adv_tx,
  290. session, PB_ADV);
  291. }
  292. /* Send CFM once per received request */
  293. send_open_cfm(session);
  294. break;
  295. case PB_ADV_CLOSE:
  296. l_debug("Link closed notification: %2.2x", pkt[0]);
  297. session->close_cb(session->user_data, pkt[0]);
  298. break;
  299. case PB_ADV_ACK:
  300. if (!session->opened)
  301. return;
  302. if (trans_num != session->local_trans_num)
  303. return;
  304. if (session->local_acked > trans_num)
  305. return;
  306. mesh_send_cancel(filter, sizeof(filter));
  307. session->local_acked = trans_num;
  308. session->ack_cb(session->user_data, trans_num);
  309. break;
  310. default: /* DATA SEGMENT */
  311. if (!session->opened)
  312. return;
  313. if (trans_num == session->last_peer_trans_num) {
  314. send_ack(session, trans_num);
  315. return;
  316. }
  317. switch(type & 0x03) {
  318. case 0x00:
  319. session->peer_trans_num = trans_num;
  320. session->exp_len = l_get_be16(pkt);
  321. l_debug("PB-ADV start with %u fragments, %d octets",
  322. type >> 2, session->exp_len);
  323. if (session->exp_len > sizeof(session->sar)) {
  324. l_debug("Incoming length exceeded: %d",
  325. session->exp_len);
  326. return;
  327. }
  328. session->exp_fcs = l_get_u8(pkt + 2);
  329. session->exp_segs = 0xff >> (7 - (type >> 2));
  330. /* Save first segment */
  331. memcpy(session->sar, pkt + 3, len - 3);
  332. session->got_segs |= 1;
  333. break;
  334. case 0x02:
  335. session->peer_trans_num = trans_num;
  336. offset = 20 + (((type >> 2) - 1) * 23);
  337. if (offset + len - 3 > sizeof(session->sar)) {
  338. l_debug("Length exceeded: %d",
  339. session->exp_len);
  340. return;
  341. }
  342. l_debug("Processing fragment %u", type >> 2);
  343. memcpy(session->sar + offset, pkt, len);
  344. session->got_segs |= 1 << (type >> 2);
  345. break;
  346. default:
  347. /* Malformed or unrecognized */
  348. return;
  349. }
  350. if (session->got_segs != session->exp_segs)
  351. return;
  352. /* Validate RXed packet and pass up to Provisioning */
  353. if (!mesh_crypto_check_fcs(session->sar,
  354. session->exp_len,
  355. session->exp_fcs)) {
  356. /* This can be a false negative if first
  357. * segment missed, and can almost always
  358. * be ignored.
  359. */
  360. l_debug("Invalid FCS");
  361. return;
  362. }
  363. send_ack(session, session->peer_trans_num);
  364. if (session->last_peer_trans_num != session->peer_trans_num) {
  365. session->got_segs = 0;
  366. session->last_peer_trans_num = session->peer_trans_num;
  367. session->rx_cb(session->user_data, session->sar,
  368. session->exp_len);
  369. }
  370. }
  371. }
  372. bool pb_adv_reg(bool initiator, mesh_prov_open_func_t open_cb,
  373. mesh_prov_close_func_t close_cb,
  374. mesh_prov_receive_func_t rx_cb, mesh_prov_ack_func_t ack_cb,
  375. uint8_t uuid[16], void *user_data)
  376. {
  377. struct pb_adv_session *session, *old_session;
  378. if (!pb_sessions)
  379. pb_sessions = l_queue_new();
  380. old_session = l_queue_find(pb_sessions, uuid_match, uuid);
  381. /* Reject 2nd session if not looping back */
  382. if (l_queue_length(pb_sessions) && !old_session)
  383. return false;
  384. /* Reject looping to more than one session or with same role*/
  385. if (old_session && (old_session->loop ||
  386. old_session->initiator == initiator))
  387. return false;
  388. session = l_new(struct pb_adv_session, 1);
  389. session->open_cb = open_cb;
  390. session->close_cb = close_cb;
  391. session->rx_cb = rx_cb;
  392. session->ack_cb = ack_cb;
  393. session->user_data = user_data;
  394. session->initiator = initiator;
  395. memcpy(session->uuid, uuid, 16);
  396. l_queue_push_head(pb_sessions, session);
  397. if (initiator) {
  398. l_getrandom(&session->link_id, sizeof(session->link_id));
  399. session->tx_timeout = l_timeout_create(60, tx_timeout,
  400. session, NULL);
  401. }
  402. /* Setup Loop-back if complementary session with same UUID */
  403. if (old_session) {
  404. session->loop = old_session;
  405. old_session->loop = session;
  406. mesh_unreg_prov_rx(pb_adv_packet);
  407. if (initiator)
  408. send_open_req(session);
  409. else
  410. send_open_req(old_session);
  411. return true;
  412. }
  413. mesh_reg_prov_rx(pb_adv_packet, session);
  414. if (initiator)
  415. send_open_req(session);
  416. return true;
  417. }
  418. void pb_adv_unreg(void *user_data)
  419. {
  420. struct pb_adv_session *session = l_queue_find(pb_sessions,
  421. user_match, user_data);
  422. if (!session)
  423. return;
  424. l_timeout_remove(session->tx_timeout);
  425. session->tx_timeout = NULL;
  426. send_close_ind(session, 0);
  427. l_queue_remove(pb_sessions, session);
  428. l_free(session);
  429. if (!l_queue_length(pb_sessions)) {
  430. l_queue_destroy(pb_sessions, l_free);
  431. pb_sessions = NULL;
  432. }
  433. }