rpl.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2020 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <fcntl.h>
  15. #include <limits.h>
  16. #include <stdio.h>
  17. #include <unistd.h>
  18. #include <dirent.h>
  19. #include <sys/stat.h>
  20. #include <ell/ell.h>
  21. #include "mesh/mesh-defs.h"
  22. #include "mesh/node.h"
  23. #include "mesh/net.h"
  24. #include "mesh/util.h"
  25. #include "mesh/rpl.h"
  26. const char *rpl_dir = "/rpl";
  27. bool rpl_put_entry(struct mesh_node *node, uint16_t src, uint32_t iv_index,
  28. uint32_t seq)
  29. {
  30. const char *node_path;
  31. char src_file[PATH_MAX];
  32. char seq_txt[7];
  33. bool result = false;
  34. DIR *dir;
  35. int fd;
  36. if (!IS_UNICAST(src))
  37. return false;
  38. node_path = node_get_storage_dir(node);
  39. if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
  40. return false;
  41. snprintf(src_file, PATH_MAX, "%s%s/%8.8x", node_path, rpl_dir,
  42. iv_index);
  43. dir = opendir(src_file);
  44. if (!dir)
  45. mkdir(src_file, 0755);
  46. else
  47. closedir(dir);
  48. snprintf(src_file, PATH_MAX, "%s%s/%8.8x/%4.4x", node_path, rpl_dir,
  49. iv_index, src);
  50. fd = open(src_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
  51. if (fd >= 0) {
  52. snprintf(seq_txt, 7, "%6.6x", seq);
  53. if (write(fd, seq_txt, 6) == 6)
  54. result = true;
  55. close(fd);
  56. }
  57. if (!result)
  58. return false;
  59. /* Delete RPL entry from old iv_index (if it exists) */
  60. iv_index--;
  61. snprintf(src_file, PATH_MAX, "%s%s/%8.8x/%4.4x", node_path, rpl_dir,
  62. iv_index, src);
  63. remove(src_file);
  64. return result;
  65. }
  66. void rpl_del_entry(struct mesh_node *node, uint16_t src)
  67. {
  68. const char *node_path;
  69. char rpl_path[PATH_MAX];
  70. struct dirent *entry;
  71. DIR *dir;
  72. if (!IS_UNICAST(src))
  73. return;
  74. node_path = node_get_storage_dir(node);
  75. if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
  76. return;
  77. snprintf(rpl_path, PATH_MAX, "%s%s", node_path, rpl_dir);
  78. dir = opendir(rpl_path);
  79. if (!dir)
  80. return;
  81. /* Remove all instances of src address */
  82. while ((entry = readdir(dir)) != NULL) {
  83. if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
  84. snprintf(rpl_path, PATH_MAX, "%s%s/%s/%4.4x",
  85. node_path, rpl_dir, entry->d_name, src);
  86. remove(rpl_path);
  87. }
  88. }
  89. closedir(dir);
  90. }
  91. static bool match_src(const void *a, const void *b)
  92. {
  93. const struct mesh_rpl *rpl = a;
  94. uint16_t src = L_PTR_TO_UINT(b);
  95. return rpl->src == src;
  96. }
  97. static void get_entries(const char *iv_path, struct l_queue *rpl_list)
  98. {
  99. struct mesh_rpl *rpl;
  100. struct dirent *entry;
  101. DIR *dir;
  102. int fd;
  103. const char *iv_txt;
  104. char src_path[PATH_MAX];
  105. char seq_txt[7];
  106. uint32_t iv_index, seq;
  107. uint16_t src;
  108. dir = opendir(iv_path);
  109. if (!dir)
  110. return;
  111. iv_txt = basename(iv_path);
  112. if (sscanf(iv_txt, "%08x", &iv_index) != 1) {
  113. closedir(dir);
  114. return;
  115. }
  116. memset(seq_txt, 0, sizeof(seq_txt));
  117. while ((entry = readdir(dir)) != NULL) {
  118. /* RPL sequences are stored in src files under iv_index */
  119. if (entry->d_type == DT_REG) {
  120. if (sscanf(entry->d_name, "%04hx", &src) != 1)
  121. continue;
  122. snprintf(src_path, PATH_MAX, "%s/%4.4x", iv_path, src);
  123. fd = open(src_path, O_RDONLY);
  124. if (fd < 0)
  125. continue;
  126. if (read(fd, seq_txt, 6) == 6 &&
  127. sscanf(seq_txt, "%06x", &seq) == 1) {
  128. rpl = l_queue_find(rpl_list, match_src,
  129. L_UINT_TO_PTR(src));
  130. if (rpl) {
  131. /* Replace older entries */
  132. if (rpl->iv_index < iv_index) {
  133. rpl->iv_index = iv_index;
  134. rpl->seq = seq;
  135. }
  136. } else if (seq <= SEQ_MASK && IS_UNICAST(src)) {
  137. rpl = l_new(struct mesh_rpl, 1);
  138. rpl->src = src;
  139. rpl->iv_index = iv_index;
  140. rpl->seq = seq;
  141. l_queue_push_head(rpl_list, rpl);
  142. }
  143. }
  144. close(fd);
  145. }
  146. }
  147. closedir(dir);
  148. }
  149. bool rpl_get_list(struct mesh_node *node, struct l_queue *rpl_list)
  150. {
  151. const char *node_path;
  152. struct dirent *entry;
  153. char *rpl_path;
  154. size_t len;
  155. DIR *dir;
  156. if (!rpl_list)
  157. return false;
  158. node_path = node_get_storage_dir(node);
  159. len = strlen(node_path) + strlen(rpl_dir) + 15;
  160. if (len > PATH_MAX)
  161. return false;
  162. rpl_path = l_malloc(len);
  163. snprintf(rpl_path, len, "%s%s", node_path, rpl_dir);
  164. dir = opendir(rpl_path);
  165. if (!dir) {
  166. l_error("Failed to read RPL dir: %s", rpl_path);
  167. l_free(rpl_path);
  168. return false;
  169. }
  170. while ((entry = readdir(dir)) != NULL) {
  171. /* RPL sequences are stored in files under iv_indexs */
  172. if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
  173. snprintf(rpl_path, len, "%s%s/%s",
  174. node_path, rpl_dir, entry->d_name);
  175. get_entries(rpl_path, rpl_list);
  176. }
  177. }
  178. l_free(rpl_path);
  179. closedir(dir);
  180. return true;
  181. }
  182. void rpl_update(struct mesh_node *node, uint32_t cur)
  183. {
  184. uint32_t old = cur - 1;
  185. const char *node_path;
  186. struct dirent *entry;
  187. char path[PATH_MAX];
  188. DIR *dir;
  189. node_path = node_get_storage_dir(node);
  190. if (!node_path)
  191. return;
  192. if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
  193. return;
  194. /* Make sure path exists */
  195. snprintf(path, PATH_MAX, "%s%s", node_path, rpl_dir);
  196. mkdir(path, 0755);
  197. dir = opendir(path);
  198. if (!dir)
  199. return;
  200. /* Cleanup any stale or malformed trees */
  201. while ((entry = readdir(dir)) != NULL) {
  202. if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
  203. uint32_t val;
  204. bool del = false;
  205. if (strlen(entry->d_name) != 8)
  206. del = true;
  207. else if (sscanf(entry->d_name, "%08x", &val) != 1)
  208. del = true;
  209. /* Delete all invalid iv_index trees */
  210. if (del || (val != cur && val != old)) {
  211. snprintf(path, PATH_MAX, "%s%s/%s",
  212. node_path, rpl_dir, entry->d_name);
  213. del_path(path);
  214. }
  215. }
  216. }
  217. closedir(dir);
  218. }
  219. bool rpl_init(const char *node_path)
  220. {
  221. char path[PATH_MAX];
  222. if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
  223. return false;
  224. snprintf(path, PATH_MAX, "%s%s", node_path, rpl_dir);
  225. mkdir(path, 0755);
  226. return true;
  227. }