rpl.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Bluetooth Mesh */
  2. /*
  3. * SPDX-FileCopyrightText: 2017 Intel Corporation
  4. * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. */
  8. #include <string.h>
  9. #include <errno.h>
  10. #include "mesh/config.h"
  11. #include "mesh/trace.h"
  12. #include "mesh.h"
  13. #include "settings.h"
  14. void bt_mesh_update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx)
  15. {
  16. rpl->src = rx->ctx.addr;
  17. rpl->seq = rx->seq;
  18. rpl->old_iv = rx->old_iv;
  19. if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
  20. bt_mesh_store_rpl(rpl);
  21. }
  22. }
  23. /* Check the Replay Protection List for a replay attempt. If non-NULL match
  24. * parameter is given the RPL slot is returned but it is not immediately
  25. * updated (needed for segmented messages), whereas if a NULL match is given
  26. * the RPL is immediately updated (used for unsegmented messages).
  27. */
  28. static bool rpl_check_and_store(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
  29. {
  30. for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
  31. struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
  32. /* Empty slot */
  33. if (rpl->src == BLE_MESH_ADDR_UNASSIGNED) {
  34. if (match) {
  35. *match = rpl;
  36. } else {
  37. bt_mesh_update_rpl(rpl, rx);
  38. }
  39. return false;
  40. }
  41. /* Existing slot for given address */
  42. if (rpl->src == rx->ctx.addr) {
  43. if (rx->old_iv && !rpl->old_iv) {
  44. return true;
  45. }
  46. if ((!rx->old_iv && rpl->old_iv) ||
  47. rpl->seq < rx->seq) {
  48. if (match) {
  49. *match = rpl;
  50. } else {
  51. bt_mesh_update_rpl(rpl, rx);
  52. }
  53. return false;
  54. }
  55. return true;
  56. }
  57. }
  58. BT_ERR("RPL is full!");
  59. return true;
  60. }
  61. bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
  62. {
  63. /* Don't bother checking messages from ourselves */
  64. if (rx->net_if == BLE_MESH_NET_IF_LOCAL) {
  65. return false;
  66. }
  67. /* The RPL is used only for the local node */
  68. if (!rx->local_match) {
  69. return false;
  70. }
  71. return rpl_check_and_store(rx, match);
  72. }
  73. void bt_mesh_rpl_update(void)
  74. {
  75. /* Discard "old old" IV Index entries from RPL and flag
  76. * any other ones (which are valid) as old.
  77. */
  78. for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
  79. struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
  80. if (rpl->src) {
  81. if (rpl->old_iv) {
  82. (void)memset(rpl, 0, sizeof(*rpl));
  83. } else {
  84. rpl->old_iv = true;
  85. }
  86. if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
  87. bt_mesh_store_rpl(rpl);
  88. }
  89. }
  90. }
  91. }
  92. void bt_mesh_rpl_reset_single(uint16_t src, bool erase)
  93. {
  94. if (!BLE_MESH_ADDR_IS_UNICAST(src)) {
  95. return;
  96. }
  97. for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
  98. if (src == bt_mesh.rpl[i].src) {
  99. memset(&bt_mesh.rpl[i], 0, sizeof(struct bt_mesh_rpl));
  100. if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && erase) {
  101. bt_mesh_clear_rpl_single(src);
  102. }
  103. }
  104. }
  105. }
  106. void bt_mesh_rpl_reset(bool erase)
  107. {
  108. (void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
  109. if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && erase) {
  110. bt_mesh_clear_rpl();
  111. }
  112. }