mesh-db.c 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2019-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 <dirent.h>
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <ftw.h>
  18. #include <libgen.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <time.h>
  22. #include <unistd.h>
  23. #include <ell/ell.h>
  24. #include <json-c/json.h>
  25. #include "mesh/mesh-defs.h"
  26. #include "mesh/util.h"
  27. #include "tools/mesh/keys.h"
  28. #include "tools/mesh/remote.h"
  29. #include "tools/mesh/cfgcli.h"
  30. #include "tools/mesh/model.h"
  31. #include "tools/mesh/mesh-db.h"
  32. #define KEY_IDX_INVALID NET_IDX_INVALID
  33. #define DEFAULT_LOCATION 0x0000
  34. struct mesh_db {
  35. json_object *jcfg;
  36. char *cfg_fname;
  37. uint8_t token[8];
  38. };
  39. static struct mesh_db *cfg;
  40. static const char *bak_ext = ".bak";
  41. static const char *tmp_ext = ".tmp";
  42. static const char *js_schema = "http://json-schema.org/draft-04/schema#";
  43. static const char *schema_id = "http://www.bluetooth.com/specifications/"
  44. "assigned-numbers/mesh-profile/"
  45. "cdb-schema.json#";
  46. const char *schema_version = "1.0.0";
  47. static bool add_string(json_object *jobj, const char *desc, const char *str)
  48. {
  49. json_object *jstring = json_object_new_string(str);
  50. if (!jstring)
  51. return false;
  52. /* Overwrite old value if present */
  53. json_object_object_del(jobj, desc);
  54. json_object_object_add(jobj, desc, jstring);
  55. return true;
  56. }
  57. static bool set_timestamp(json_object *jobj)
  58. {
  59. time_t time_raw;
  60. struct tm *tp;
  61. char buf[80];
  62. time(&time_raw);
  63. tp = gmtime(&time_raw);
  64. strftime(buf, 80, "%FT%TZ", tp);
  65. return add_string(jobj, "timestamp", buf);
  66. }
  67. static bool save_config_file(const char *fname)
  68. {
  69. FILE *outfile;
  70. const char *str;
  71. bool result = false;
  72. outfile = fopen(fname, "w");
  73. if (!outfile) {
  74. l_error("Failed to save configuration to %s", cfg->cfg_fname);
  75. return false;
  76. }
  77. set_timestamp(cfg->jcfg);
  78. str = json_object_to_json_string_ext(cfg->jcfg,
  79. JSON_C_TO_STRING_PRETTY);
  80. if (fwrite(str, sizeof(char), strlen(str), outfile) < strlen(str))
  81. l_warn("Incomplete write of mesh configuration");
  82. else
  83. result = true;
  84. fclose(outfile);
  85. return result;
  86. }
  87. static bool save_config(void)
  88. {
  89. char *fname_tmp, *fname_bak, *fname_cfg;
  90. bool result = false;
  91. fname_cfg = cfg->cfg_fname;
  92. fname_tmp = l_strdup_printf("%s%s", fname_cfg, tmp_ext);
  93. fname_bak = l_strdup_printf("%s%s", fname_cfg, bak_ext);
  94. remove(fname_tmp);
  95. result = save_config_file(fname_tmp);
  96. if (result) {
  97. remove(fname_bak);
  98. rename(fname_cfg, fname_bak);
  99. rename(fname_tmp, fname_cfg);
  100. }
  101. remove(fname_tmp);
  102. l_free(fname_tmp);
  103. l_free(fname_bak);
  104. return result;
  105. }
  106. static void release_config(void)
  107. {
  108. l_free(cfg->cfg_fname);
  109. json_object_put(cfg->jcfg);
  110. l_free(cfg);
  111. cfg = NULL;
  112. }
  113. static json_object *get_node_by_unicast(json_object *jcfg, uint16_t unicast)
  114. {
  115. json_object *jarray;
  116. int i, sz;
  117. if (!json_object_object_get_ex(jcfg, "nodes", &jarray))
  118. return NULL;
  119. if (!jarray || json_object_get_type(jarray) != json_type_array)
  120. return NULL;
  121. sz = json_object_array_length(jarray);
  122. for (i = 0; i < sz; ++i) {
  123. json_object *jentry, *jval;
  124. uint16_t addr;
  125. const char *str;
  126. jentry = json_object_array_get_idx(jarray, i);
  127. if (!json_object_object_get_ex(jentry, "unicastAddress",
  128. &jval))
  129. return NULL;
  130. str = json_object_get_string(jval);
  131. if (sscanf(str, "%04hx", &addr) != 1)
  132. continue;
  133. if (addr == unicast)
  134. return jentry;
  135. }
  136. return NULL;
  137. }
  138. static bool get_int(json_object *jobj, const char *keyword, int *value)
  139. {
  140. json_object *jvalue;
  141. if (!json_object_object_get_ex(jobj, keyword, &jvalue))
  142. return false;
  143. *value = json_object_get_int(jvalue);
  144. if (errno == EINVAL) {
  145. l_error("Error: %s should contain an integer value\n",
  146. keyword);
  147. return false;
  148. }
  149. return true;
  150. }
  151. static bool write_int(json_object *jobj, const char *keyword, int val)
  152. {
  153. json_object *jval;
  154. jval = json_object_new_int(val);
  155. if (!jval)
  156. return false;
  157. /* Overwrite old value if present */
  158. json_object_object_del(jobj, keyword);
  159. json_object_object_add(jobj, keyword, jval);
  160. return true;
  161. }
  162. static bool get_bool(json_object *jobj, const char *keyword, bool *value)
  163. {
  164. json_object *jvalue;
  165. if (!json_object_object_get_ex(jobj, keyword, &jvalue))
  166. return false;
  167. if (json_object_get_type(jvalue) != json_type_boolean) {
  168. l_error("Error: %s should contain a boolean value\n",
  169. keyword);
  170. return false;
  171. }
  172. *value = json_object_get_boolean(jvalue);
  173. return true;
  174. }
  175. static bool write_bool(json_object *jobj, const char *keyword, bool val)
  176. {
  177. json_object *jval;
  178. jval = json_object_new_boolean(val);
  179. if (!jval)
  180. return false;
  181. /* Overwrite old value if present */
  182. json_object_object_del(jobj, keyword);
  183. json_object_object_add(jobj, keyword, jval);
  184. return true;
  185. }
  186. static json_object *get_key_object(json_object *jarray, uint16_t idx)
  187. {
  188. int i, sz = json_object_array_length(jarray);
  189. for (i = 0; i < sz; ++i) {
  190. json_object *jentry;
  191. int jidx;
  192. jentry = json_object_array_get_idx(jarray, i);
  193. if (!get_int(jentry, "index", &jidx))
  194. return NULL;
  195. if (jidx == idx)
  196. return jentry;
  197. }
  198. return NULL;
  199. }
  200. static bool write_uint16_hex(json_object *jobj, const char *desc,
  201. uint16_t value)
  202. {
  203. json_object *jstring;
  204. char buf[5];
  205. snprintf(buf, 5, "%4.4x", value);
  206. jstring = json_object_new_string(buf);
  207. if (!jstring)
  208. return false;
  209. /* Overwrite old value if present */
  210. json_object_object_del(jobj, desc);
  211. json_object_object_add(jobj, desc, jstring);
  212. return true;
  213. }
  214. static bool write_uint32_hex(json_object *jobj, const char *desc, uint32_t val)
  215. {
  216. json_object *jstring;
  217. char buf[9];
  218. snprintf(buf, 9, "%8.8x", val);
  219. jstring = json_object_new_string(buf);
  220. if (!jstring)
  221. return false;
  222. /* Overwrite old value if present */
  223. json_object_object_del(jobj, desc);
  224. json_object_object_add(jobj, desc, jstring);
  225. return true;
  226. }
  227. static json_object *get_node_by_uuid(json_object *jcfg, uint8_t uuid[16])
  228. {
  229. json_object *jarray = NULL;
  230. char buf[37];
  231. int i, sz;
  232. if (!l_uuid_to_string(uuid, buf, sizeof(buf)))
  233. return NULL;
  234. json_object_object_get_ex(jcfg, "nodes", &jarray);
  235. if (!jarray || json_object_get_type(jarray) != json_type_array)
  236. return NULL;
  237. sz = json_object_array_length(jarray);
  238. for (i = 0; i < sz; ++i) {
  239. json_object *jentry, *jval;
  240. const char *str;
  241. jentry = json_object_array_get_idx(jarray, i);
  242. if (!json_object_object_get_ex(jentry, "UUID", &jval))
  243. return NULL;
  244. str = json_object_get_string(jval);
  245. if (strlen(str) != 36)
  246. continue;
  247. if (!strcmp(buf, str))
  248. return jentry;
  249. }
  250. return NULL;
  251. }
  252. static bool add_u8_8(json_object *jobj, const char *desc,
  253. const uint8_t value[8])
  254. {
  255. json_object *jstring;
  256. char buf[17];
  257. hex2str((uint8_t *) value, 8, buf, 17);
  258. jstring = json_object_new_string(buf);
  259. if (!jstring)
  260. return false;
  261. /* Overwrite old value if present */
  262. json_object_object_del(jobj, desc);
  263. json_object_object_add(jobj, desc, jstring);
  264. return true;
  265. }
  266. static bool add_u8_16(json_object *jobj, const char *desc,
  267. const uint8_t value[16])
  268. {
  269. json_object *jstring;
  270. char buf[33];
  271. hex2str((uint8_t *) value, 16, buf, 33);
  272. jstring = json_object_new_string(buf);
  273. if (!jstring)
  274. return false;
  275. /* Overwrite old value if present */
  276. json_object_object_del(jobj, desc);
  277. json_object_object_add(jobj, desc, jstring);
  278. return true;
  279. }
  280. static bool get_token(json_object *jobj, uint8_t token[8])
  281. {
  282. json_object *jval;
  283. const char *str;
  284. if (!token)
  285. return false;
  286. if (!json_object_object_get_ex(jobj, "token", &jval))
  287. return false;
  288. str = json_object_get_string(jval);
  289. if (!str2hex(str, strlen(str), token, 8))
  290. return false;
  291. return true;
  292. }
  293. static uint16_t node_parse_key(json_object *jarray, int i)
  294. {
  295. json_object *jkey;
  296. int idx;
  297. jkey = json_object_array_get_idx(jarray, i);
  298. if (!jkey)
  299. return KEY_IDX_INVALID;
  300. if (!get_int(jkey, "index", &idx))
  301. return KEY_IDX_INVALID;
  302. return (uint16_t)idx;
  303. }
  304. static bool node_check_key_updated(json_object *jarray, int i, bool *updated)
  305. {
  306. json_object *jkey;
  307. jkey = json_object_array_get_idx(jarray, i);
  308. if (!jkey)
  309. return false;
  310. if (!get_bool(jkey, "updated", updated))
  311. return false;
  312. return true;
  313. }
  314. static int compare_group_addr(const void *a, const void *b, void *user_data)
  315. {
  316. const struct mesh_group *grp0 = a;
  317. const struct mesh_group *grp1 = b;
  318. if (grp0->addr < grp1->addr)
  319. return -1;
  320. if (grp0->addr > grp1->addr)
  321. return 1;
  322. return 0;
  323. }
  324. static bool load_composition(json_object *jnode, uint16_t unicast)
  325. {
  326. json_object *jarray;
  327. int i, ele_cnt;
  328. if (!json_object_object_get_ex(jnode, "elements", &jarray))
  329. return false;
  330. if (json_object_get_type(jarray) != json_type_array)
  331. return false;
  332. ele_cnt = json_object_array_length(jarray);
  333. for (i = 0; i < ele_cnt; ++i) {
  334. json_object *jentry, *jval, *jmods;
  335. int32_t index;
  336. int k, mod_cnt;
  337. jentry = json_object_array_get_idx(jarray, i);
  338. if (!json_object_object_get_ex(jentry, "index", &jval))
  339. return false;
  340. index = json_object_get_int(jval);
  341. if (index > 0xff)
  342. return false;
  343. if (!json_object_object_get_ex(jentry, "models", &jmods))
  344. return false;
  345. mod_cnt = json_object_array_length(jmods);
  346. for (k = 0; k < mod_cnt; ++k) {
  347. json_object *jmod, *jid;
  348. uint32_t mod_id, len;
  349. const char *str;
  350. jmod = json_object_array_get_idx(jmods, k);
  351. if (!json_object_object_get_ex(jmod, "modelId", &jid))
  352. return false;
  353. str = json_object_get_string(jid);
  354. len = strlen(str);
  355. if (len != 4 && len != 8)
  356. return false;
  357. if ((len == 4) && (sscanf(str, "%04x", &mod_id) != 1))
  358. return false;
  359. if ((len == 8) && (sscanf(str, "%08x", &mod_id) != 1))
  360. return false;
  361. remote_set_model(unicast, index, mod_id, len == 8);
  362. }
  363. }
  364. return true;
  365. }
  366. static void load_remotes(json_object *jcfg)
  367. {
  368. json_object *jnodes;
  369. int i, sz, node_count = 0;
  370. json_object_object_get_ex(jcfg, "nodes", &jnodes);
  371. if (!jnodes || json_object_get_type(jnodes) != json_type_array)
  372. return;
  373. sz = json_object_array_length(jnodes);
  374. for (i = 0; i < sz; ++i) {
  375. json_object *jnode, *jval, *jarray;
  376. uint8_t uuid[16];
  377. uint16_t unicast, key_idx;
  378. const char *str;
  379. int ele_cnt, key_cnt;
  380. int j;
  381. jnode = json_object_array_get_idx(jnodes, i);
  382. if (!jnode)
  383. continue;
  384. if (!json_object_object_get_ex(jnode, "UUID", &jval))
  385. continue;
  386. str = json_object_get_string(jval);
  387. if (strlen(str) != 36)
  388. continue;
  389. if (!l_uuid_from_string(str, uuid))
  390. continue;
  391. if (!json_object_object_get_ex(jnode, "unicastAddress", &jval))
  392. continue;
  393. str = json_object_get_string(jval);
  394. if (sscanf(str, "%04hx", &unicast) != 1)
  395. continue;
  396. json_object_object_get_ex(jnode, "elements", &jarray);
  397. if (!jarray || json_object_get_type(jarray) != json_type_array)
  398. continue;
  399. ele_cnt = json_object_array_length(jarray);
  400. if (ele_cnt > MAX_ELE_COUNT)
  401. continue;
  402. json_object_object_get_ex(jnode, "netKeys", &jarray);
  403. if (!jarray || json_object_get_type(jarray) != json_type_array)
  404. continue;
  405. key_cnt = json_object_array_length(jarray);
  406. if (key_cnt < 0)
  407. continue;
  408. key_idx = node_parse_key(jarray, 0);
  409. if (key_idx == KEY_IDX_INVALID)
  410. continue;
  411. remote_add_node((const uint8_t *)uuid, unicast, ele_cnt,
  412. key_idx);
  413. for (j = 1; j < key_cnt; j++) {
  414. bool updated = false;
  415. key_idx = node_parse_key(jarray, j);
  416. if (key_idx == KEY_IDX_INVALID)
  417. continue;
  418. remote_add_net_key(unicast, key_idx, false);
  419. node_check_key_updated(jarray, j, &updated);
  420. remote_update_net_key(unicast, key_idx, updated, false);
  421. }
  422. json_object_object_get_ex(jnode, "appKeys", &jarray);
  423. if (!jarray || json_object_get_type(jarray) != json_type_array)
  424. continue;
  425. key_cnt = json_object_array_length(jarray);
  426. for (j = 0; j < key_cnt; j++) {
  427. bool updated = false;
  428. key_idx = node_parse_key(jarray, j);
  429. if (key_idx == KEY_IDX_INVALID)
  430. continue;
  431. remote_add_app_key(unicast, key_idx, false);
  432. node_check_key_updated(jarray, j, &updated);
  433. remote_update_app_key(unicast, key_idx, updated, false);
  434. }
  435. if (!load_composition(jnode, unicast))
  436. continue;
  437. /* If "crpl" is present, composition's is available */
  438. jval = NULL;
  439. if (json_object_object_get_ex(jnode, "crpl", &jval) && jval)
  440. remote_set_composition(unicast, true);
  441. /* TODO: Add the rest of the configuration */
  442. node_count++;
  443. }
  444. if (node_count != sz)
  445. l_warn("The remote node configuration load is incomplete!");
  446. }
  447. static bool add_app_key(json_object *jobj, uint16_t net_idx, uint16_t app_idx)
  448. {
  449. json_object *jkey, *jarray;
  450. char buf[12];
  451. json_object_object_get_ex(jobj, "appKeys", &jarray);
  452. if (!jarray || json_object_get_type(jarray) != json_type_array)
  453. return false;
  454. jkey = json_object_new_object();
  455. snprintf(buf, 12, "AppKey %4.4x", app_idx);
  456. if (!add_string(jkey, "name", buf))
  457. goto fail;
  458. if (!write_int(jkey, "boundNetKey", (int)net_idx))
  459. goto fail;
  460. if (!write_int(jkey, "index", (int)app_idx))
  461. goto fail;
  462. json_object_array_add(jarray, jkey);
  463. return true;
  464. fail:
  465. json_object_put(jkey);
  466. return false;
  467. }
  468. static bool add_node_key(json_object *jobj, const char *desc, uint16_t idx)
  469. {
  470. json_object *jkey, *jarray;
  471. json_object_object_get_ex(jobj, desc, &jarray);
  472. if (!jarray || json_object_get_type(jarray) != json_type_array)
  473. return false;
  474. jkey = json_object_new_object();
  475. if (!write_int(jkey, "index", (int)idx))
  476. goto fail;
  477. if (!write_bool(jkey, "updated", false))
  478. goto fail;
  479. json_object_array_add(jarray, jkey);
  480. return save_config();
  481. fail:
  482. json_object_put(jkey);
  483. return false;
  484. }
  485. bool mesh_db_node_set_ttl(uint16_t unicast, uint8_t ttl)
  486. {
  487. json_object *jnode;
  488. if (!cfg || !cfg->jcfg)
  489. return false;
  490. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  491. if (!jnode)
  492. return false;
  493. if (!write_int(jnode, "defaultTTL", ttl))
  494. return false;
  495. return save_config();
  496. }
  497. static bool add_transmit_info(json_object *jobj, int cnt, int interval,
  498. const char *desc)
  499. {
  500. json_object *jtxmt;
  501. json_object_object_del(jobj, desc);
  502. jtxmt = json_object_new_object();
  503. if (!write_int(jtxmt, "count", cnt))
  504. goto fail;
  505. if (!write_int(jtxmt, "interval", interval))
  506. goto fail;
  507. json_object_object_add(jobj, desc, jtxmt);
  508. return true;
  509. fail:
  510. json_object_put(jtxmt);
  511. return false;
  512. }
  513. bool mesh_db_node_set_net_transmit(uint16_t unicast, uint8_t cnt,
  514. uint16_t interval)
  515. {
  516. json_object *jnode;
  517. if (!cfg || !cfg->jcfg)
  518. return false;
  519. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  520. if (!jnode)
  521. return false;
  522. if (!add_transmit_info(jnode, cnt, interval, "networkTransmit"))
  523. return false;
  524. return save_config();
  525. }
  526. static bool set_feature(json_object *jnode, const char *desc, uint8_t feature)
  527. {
  528. json_object *jobj;
  529. if (feature > MESH_MODE_UNSUPPORTED)
  530. return false;
  531. jobj = json_object_object_get(jnode, "features");
  532. if (!jobj) {
  533. jobj = json_object_new_object();
  534. json_object_object_add(jnode, "features", jobj);
  535. }
  536. if (!write_int(jobj, desc, feature))
  537. return false;
  538. return save_config();
  539. }
  540. bool mesh_db_node_set_relay(uint16_t unicast, uint8_t relay, uint8_t cnt,
  541. uint16_t interval)
  542. {
  543. json_object *jnode;
  544. if (!cfg || !cfg->jcfg)
  545. return false;
  546. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  547. if (!jnode)
  548. return false;
  549. if (relay < MESH_MODE_UNSUPPORTED &&
  550. !add_transmit_info(jnode, cnt, interval, "relayRetransmit"))
  551. return false;
  552. return set_feature(jnode, "relay", relay);
  553. }
  554. bool mesh_db_node_set_proxy(uint16_t unicast, uint8_t proxy)
  555. {
  556. json_object *jnode;
  557. if (!cfg || !cfg->jcfg)
  558. return false;
  559. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  560. if (!jnode)
  561. return false;
  562. return set_feature(jnode, "proxy", proxy);
  563. }
  564. bool mesh_db_node_set_friend(uint16_t unicast, uint8_t friend)
  565. {
  566. json_object *jnode;
  567. if (!cfg || !cfg->jcfg)
  568. return false;
  569. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  570. if (!jnode)
  571. return false;
  572. return set_feature(jnode, "friend", friend);
  573. }
  574. bool mesh_db_node_set_beacon(uint16_t unicast, bool enabled)
  575. {
  576. json_object *jnode;
  577. if (!cfg || !cfg->jcfg)
  578. return false;
  579. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  580. if (!jnode)
  581. return false;
  582. if (!write_bool(jnode, "secureNetworkBeacon", enabled))
  583. return false;
  584. return save_config();
  585. }
  586. static json_object *get_element(uint16_t unicast, uint16_t ele_addr)
  587. {
  588. json_object *jnode, *jarray;
  589. int i, ele_cnt;
  590. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  591. if (!jnode)
  592. return false;
  593. if (!json_object_object_get_ex(jnode, "elements", &jarray))
  594. return NULL;
  595. if (!jarray || json_object_get_type(jarray) != json_type_array)
  596. return NULL;
  597. ele_cnt = json_object_array_length(jarray);
  598. for (i = 0; i < ele_cnt; ++i) {
  599. json_object *jentry, *jval;
  600. int32_t index;
  601. jentry = json_object_array_get_idx(jarray, i);
  602. if (!json_object_object_get_ex(jentry, "index", &jval))
  603. return NULL;
  604. index = json_object_get_int(jval);
  605. if (index > 0xff)
  606. return NULL;
  607. if (ele_addr == unicast + index)
  608. return jentry;
  609. }
  610. return NULL;
  611. }
  612. static json_object *get_model(uint16_t unicast, uint16_t ele_addr,
  613. uint32_t mod_id, bool vendor)
  614. {
  615. json_object *jelement, *jarray;
  616. int i, sz;
  617. jelement = get_element(unicast, ele_addr);
  618. if (!jelement)
  619. return false;
  620. if (!json_object_object_get_ex(jelement, "models", &jarray))
  621. return NULL;
  622. if (!jarray || json_object_get_type(jarray) != json_type_array)
  623. return NULL;
  624. if (!vendor)
  625. mod_id = mod_id & ~VENDOR_ID_MASK;
  626. sz = json_object_array_length(jarray);
  627. for (i = 0; i < sz; ++i) {
  628. json_object *jentry, *jval;
  629. uint32_t id, len;
  630. const char *str;
  631. jentry = json_object_array_get_idx(jarray, i);
  632. if (!json_object_object_get_ex(jentry, "modelId",
  633. &jval))
  634. return NULL;
  635. str = json_object_get_string(jval);
  636. len = strlen(str);
  637. if (len != 4 && len != 8)
  638. return NULL;
  639. if ((len == 4 && vendor) || (len == 8 && !vendor))
  640. continue;
  641. if (sscanf(str, "%08x", &id) != 1)
  642. return NULL;
  643. if (id == mod_id)
  644. return jentry;
  645. }
  646. return NULL;
  647. }
  648. static void jarray_int_del(json_object *jarray, int val)
  649. {
  650. int i, sz = json_object_array_length(jarray);
  651. for (i = 0; i < sz; ++i) {
  652. json_object *jentry;
  653. jentry = json_object_array_get_idx(jarray, i);
  654. if (val == json_object_get_int(jentry)) {
  655. json_object_array_del_idx(jarray, i, 1);
  656. return;
  657. }
  658. }
  659. }
  660. static bool update_model_int_array(uint16_t unicast, uint16_t ele_addr,
  661. bool vendor, uint32_t mod_id,
  662. int val, const char *keyword, bool add)
  663. {
  664. json_object *jarray, *jmod, *jvalue;
  665. if (!cfg || !cfg->jcfg)
  666. return false;
  667. jmod = get_model(unicast, ele_addr, mod_id, vendor);
  668. if (!jmod)
  669. return false;
  670. if (!json_object_object_get_ex(jmod, keyword, &jarray))
  671. return false;
  672. if (!jarray || json_object_get_type(jarray) != json_type_array)
  673. return false;
  674. jarray_int_del(jarray, val);
  675. if (!add)
  676. return true;
  677. jvalue = json_object_new_int(val);
  678. if (!jvalue)
  679. return false;
  680. json_object_array_add(jarray, jvalue);
  681. return save_config();
  682. }
  683. bool mesh_db_node_model_bind(uint16_t unicast, uint16_t ele_addr, bool vendor,
  684. uint32_t mod_id, uint16_t app_idx)
  685. {
  686. char buf[5];
  687. snprintf(buf, 5, "%4.4x", app_idx);
  688. return update_model_int_array(unicast, ele_addr, vendor, mod_id,
  689. (int) app_idx, "bind", true);
  690. }
  691. bool mesh_db_node_model_unbind(uint16_t unicast, uint16_t ele_addr, bool vendor,
  692. uint32_t mod_id, uint16_t app_idx)
  693. {
  694. char buf[5];
  695. snprintf(buf, 5, "%4.4x", app_idx);
  696. return update_model_int_array(unicast, ele_addr, vendor, mod_id,
  697. (int) app_idx, "bind", false);
  698. }
  699. static void jarray_string_del(json_object *jarray, const char *str, size_t len)
  700. {
  701. int i, sz = json_object_array_length(jarray);
  702. for (i = 0; i < sz; ++i) {
  703. json_object *jentry;
  704. char *str_entry;
  705. jentry = json_object_array_get_idx(jarray, i);
  706. str_entry = (char *)json_object_get_string(jentry);
  707. if (str_entry && (strlen(str_entry) == len) &&
  708. !strncmp(str, str_entry, len)) {
  709. json_object_array_del_idx(jarray, i, 1);
  710. return;
  711. }
  712. }
  713. }
  714. static bool add_array_string(json_object *jarray, const char *str)
  715. {
  716. json_object *jstring;
  717. jstring = json_object_new_string(str);
  718. if (!jstring)
  719. return false;
  720. json_object_array_add(jarray, jstring);
  721. return true;
  722. }
  723. static bool update_model_string_array(uint16_t unicast, uint16_t ele_addr,
  724. bool vendor, uint32_t mod_id,
  725. const char *str, uint32_t len,
  726. const char *keyword, bool add)
  727. {
  728. json_object *jarray, *jmod;
  729. if (!cfg || !cfg->jcfg)
  730. return false;
  731. jmod = get_model(unicast, ele_addr, mod_id, vendor);
  732. if (!jmod)
  733. return false;
  734. if (!json_object_object_get_ex(jmod, keyword, &jarray))
  735. return false;
  736. if (!jarray || json_object_get_type(jarray) != json_type_array)
  737. return false;
  738. jarray_string_del(jarray, str, len);
  739. if (!add)
  740. return true;
  741. if (!add_array_string(jarray, str))
  742. return false;
  743. return save_config();
  744. }
  745. bool mesh_db_node_model_add_sub(uint16_t unicast, uint16_t ele, bool vendor,
  746. uint32_t mod_id, uint16_t addr)
  747. {
  748. char buf[5];
  749. snprintf(buf, 5, "%4.4x", addr);
  750. return update_model_string_array(unicast, ele, vendor, mod_id, buf, 4,
  751. "subscribe", true);
  752. }
  753. bool mesh_db_node_model_del_sub(uint16_t unicast, uint16_t ele, bool vendor,
  754. uint32_t mod_id, uint16_t addr)
  755. {
  756. char buf[5];
  757. snprintf(buf, 5, "%4.4x", addr);
  758. return update_model_string_array(unicast, ele, vendor, mod_id, buf, 4,
  759. "subscribe", false);
  760. }
  761. bool mesh_db_node_model_add_sub_virt(uint16_t unicast, uint16_t ele,
  762. bool vendor, uint32_t mod_id,
  763. uint8_t *label)
  764. {
  765. char buf[33];
  766. hex2str(label, 16, buf, sizeof(buf));
  767. return update_model_string_array(unicast, ele, vendor, mod_id, buf, 32,
  768. "subscribe", true);
  769. }
  770. bool mesh_db_node_model_del_sub_virt(uint16_t unicast, uint16_t ele,
  771. bool vendor, uint32_t mod_id,
  772. uint8_t *label)
  773. {
  774. char buf[33];
  775. hex2str(label, 16, buf, sizeof(buf));
  776. return update_model_string_array(unicast, ele, vendor, mod_id, buf, 32,
  777. "subscribe", false);
  778. }
  779. static json_object *delete_subs(uint16_t unicast, uint16_t ele, bool vendor,
  780. uint32_t mod_id)
  781. {
  782. json_object *jarray, *jmod;
  783. if (!cfg || !cfg->jcfg)
  784. return NULL;
  785. jmod = get_model(unicast, ele, mod_id, vendor);
  786. if (!jmod)
  787. return NULL;
  788. json_object_object_del(jmod, "subscribe");
  789. jarray = json_object_new_array();
  790. if (!jarray)
  791. return NULL;
  792. json_object_object_add(jmod, "subscribe", jarray);
  793. return jarray;
  794. }
  795. bool mesh_db_node_model_del_sub_all(uint16_t unicast, uint16_t ele, bool vendor,
  796. uint32_t mod_id)
  797. {
  798. if (!delete_subs(unicast, ele, vendor, mod_id))
  799. return false;
  800. return save_config();
  801. }
  802. static bool sub_overwrite(uint16_t unicast, uint16_t ele, bool vendor,
  803. uint32_t mod_id, char *buf)
  804. {
  805. json_object *jarray, *jstring;
  806. jarray = delete_subs(unicast, ele, vendor, mod_id);
  807. if (!jarray)
  808. return false;
  809. jstring = json_object_new_string(buf);
  810. if (!jstring)
  811. return false;
  812. json_object_array_add(jarray, jstring);
  813. return save_config();
  814. }
  815. bool mesh_db_node_model_overwrt_sub(uint16_t unicast, uint16_t ele, bool vendor,
  816. uint32_t mod_id, uint16_t addr)
  817. {
  818. char buf[5];
  819. snprintf(buf, 5, "%4.4x", addr);
  820. return sub_overwrite(unicast, ele, vendor, mod_id, buf);
  821. }
  822. bool mesh_db_node_model_overwrt_sub_virt(uint16_t unicast, uint16_t ele,
  823. bool vendor, uint32_t mod_id,
  824. uint8_t *label)
  825. {
  826. char buf[33];
  827. hex2str(label, 16, buf, sizeof(buf));
  828. return sub_overwrite(unicast, ele, vendor, mod_id, buf);
  829. }
  830. bool mesh_db_node_model_set_pub(uint16_t unicast, uint16_t ele_addr,
  831. bool vendor, uint32_t mod_id,
  832. struct model_pub *pub, bool virt)
  833. {
  834. json_object *jmod, *jpub, *jobj = NULL;
  835. if (!cfg || !cfg->jcfg)
  836. return false;
  837. jmod = get_model(unicast, ele_addr, mod_id, vendor);
  838. if (!jmod)
  839. return false;
  840. jpub = json_object_new_object();
  841. if (!virt && !write_uint16_hex(jpub, "address", pub->u.addr))
  842. goto fail;
  843. if (virt) {
  844. char buf[33];
  845. hex2str(pub->u.label, 16, buf, sizeof(buf));
  846. if (!add_string(jpub, "address", buf))
  847. goto fail;
  848. }
  849. if (!write_int(jpub, "index", pub->app_idx))
  850. goto fail;
  851. if (!write_int(jpub, "ttl", pub->ttl))
  852. goto fail;
  853. if (!write_int(jpub, "credentials", pub->cred ? 1 : 0))
  854. goto fail;
  855. if (!add_transmit_info(jpub, pub->rtx_cnt, pub->rtx_interval,
  856. "retransmit"))
  857. goto fail;
  858. jobj = json_object_new_object();
  859. if (!write_int(jobj, "numberOfSteps", pub->prd_steps))
  860. goto fail;
  861. if (!write_int(jobj, "resolution", pub->prd_res))
  862. goto fail;
  863. json_object_object_add(jpub, "period", jobj);
  864. json_object_object_del(jmod, "publish");
  865. json_object_object_add(jmod, "publish", jpub);
  866. return save_config();
  867. fail:
  868. if (jobj)
  869. json_object_put(jobj);
  870. json_object_put(jpub);
  871. return false;
  872. }
  873. bool mesh_db_node_set_hb_pub(uint16_t unicast, uint16_t dst, uint16_t net_idx,
  874. uint8_t period_log, uint8_t ttl,
  875. uint16_t features)
  876. {
  877. json_object *jnode, *jpub, *jarray = NULL;
  878. uint32_t period;
  879. if (!cfg || !cfg->jcfg)
  880. return false;
  881. if (period_log > 0x12 || ttl > 0x7F)
  882. return false;
  883. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  884. if (!jnode)
  885. return false;
  886. jpub = json_object_new_object();
  887. if (!write_uint16_hex(jpub, "address", dst))
  888. goto fail;
  889. period = period_log ? 1 << (period_log - 1) : 0;
  890. if (!write_int(jpub, "period", period))
  891. goto fail;
  892. if (!write_int(jpub, "ttl", ttl))
  893. goto fail;
  894. if (!write_int(jpub, "index", net_idx))
  895. goto fail;
  896. jarray = json_object_new_array();
  897. if (features & FEATURE_PROXY)
  898. if (!add_array_string(jarray, "proxy"))
  899. goto fail;
  900. if (features & FEATURE_RELAY)
  901. if (!add_array_string(jarray, "relay"))
  902. goto fail;
  903. if (features & FEATURE_FRIEND)
  904. if (!add_array_string(jarray, "friend"))
  905. goto fail;
  906. if (features & FEATURE_LPN)
  907. if (!add_array_string(jarray, "lowPower"))
  908. goto fail;
  909. json_object_object_add(jpub, "features", jarray);
  910. json_object_object_del(jnode, "heartbeatPub");
  911. json_object_object_add(jnode, "heartbeatPub", jpub);
  912. return save_config();
  913. fail:
  914. if (jarray)
  915. json_object_put(jarray);
  916. json_object_put(jpub);
  917. return false;
  918. }
  919. bool mesh_db_node_set_hb_sub(uint16_t unicast, uint16_t src, uint16_t dst)
  920. {
  921. json_object *jnode, *jsub;
  922. if (!cfg || !cfg->jcfg)
  923. return false;
  924. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  925. if (!jnode)
  926. return false;
  927. jsub = json_object_new_object();
  928. if (!write_uint16_hex(jsub, "source", src))
  929. goto fail;
  930. if (!write_uint16_hex(jsub, "destination", dst))
  931. goto fail;
  932. json_object_object_del(jnode, "heartbeatSub");
  933. json_object_object_add(jnode, "heartbeatSub", jsub);
  934. return save_config();
  935. fail:
  936. json_object_put(jsub);
  937. return false;
  938. }
  939. static void jarray_key_del(json_object *jarray, int16_t idx)
  940. {
  941. int i, sz = json_object_array_length(jarray);
  942. for (i = 0; i < sz; ++i) {
  943. json_object *jentry;
  944. int val;
  945. jentry = json_object_array_get_idx(jarray, i);
  946. if (!get_int(jentry, "index", &val))
  947. continue;
  948. if (val == idx) {
  949. json_object_array_del_idx(jarray, i, 1);
  950. return;
  951. }
  952. }
  953. }
  954. static bool delete_key(json_object *jobj, const char *desc, uint16_t idx)
  955. {
  956. json_object *jarray;
  957. if (!json_object_object_get_ex(jobj, desc, &jarray))
  958. return true;
  959. jarray_key_del(jarray, idx);
  960. return save_config();
  961. }
  962. bool mesh_db_node_add_net_key(uint16_t unicast, uint16_t idx)
  963. {
  964. json_object *jnode;
  965. if (!cfg || !cfg->jcfg)
  966. return false;
  967. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  968. if (!jnode)
  969. return false;
  970. return add_node_key(jnode, "netKeys", idx);
  971. }
  972. bool mesh_db_node_del_net_key(uint16_t unicast, uint16_t net_idx)
  973. {
  974. json_object *jnode;
  975. if (!cfg || !cfg->jcfg)
  976. return false;
  977. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  978. if (!jnode)
  979. return false;
  980. return delete_key(jnode, "netKeys", net_idx);
  981. }
  982. static bool key_update(uint16_t unicast, int16_t idx, bool updated,
  983. const char *desc)
  984. {
  985. json_object *jnode, *jarray;
  986. int i, sz;
  987. if (!cfg || !cfg->jcfg)
  988. return false;
  989. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  990. if (!jnode)
  991. return false;
  992. if (!json_object_object_get_ex(jnode, desc, &jarray))
  993. return false;
  994. sz = json_object_array_length(jarray);
  995. for (i = 0; i < sz; ++i) {
  996. json_object *jentry;
  997. int val;
  998. jentry = json_object_array_get_idx(jarray, i);
  999. if (!get_int(jentry, "index", &val))
  1000. continue;
  1001. if ((val == idx) && write_bool(jentry, "updated", updated))
  1002. return save_config();
  1003. }
  1004. return false;
  1005. }
  1006. bool mesh_db_node_update_net_key(uint16_t unicast, uint16_t idx, bool updated)
  1007. {
  1008. return key_update(unicast, idx, updated, "netKeys");
  1009. }
  1010. bool mesh_db_node_add_app_key(uint16_t unicast, uint16_t idx)
  1011. {
  1012. json_object *jnode;
  1013. if (!cfg || !cfg->jcfg)
  1014. return false;
  1015. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  1016. if (!jnode)
  1017. return false;
  1018. return add_node_key(jnode, "appKeys", idx);
  1019. }
  1020. bool mesh_db_node_del_app_key(uint16_t unicast, uint16_t idx)
  1021. {
  1022. json_object *jnode;
  1023. if (!cfg || !cfg->jcfg)
  1024. return false;
  1025. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  1026. if (!jnode)
  1027. return false;
  1028. return delete_key(jnode, "appKeys", idx);
  1029. }
  1030. bool mesh_db_node_update_app_key(uint16_t unicast, uint16_t idx, bool updated)
  1031. {
  1032. return key_update(unicast, idx, updated, "appKeys");
  1033. }
  1034. static bool load_keys(json_object *jobj)
  1035. {
  1036. json_object *jarray, *jentry;
  1037. int net_idx, app_idx;
  1038. int i, key_cnt;
  1039. json_object_object_get_ex(jobj, "netKeys", &jarray);
  1040. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1041. return false;
  1042. key_cnt = json_object_array_length(jarray);
  1043. if (key_cnt < 0)
  1044. return false;
  1045. for (i = 0; i < key_cnt; ++i) {
  1046. int phase;
  1047. jentry = json_object_array_get_idx(jarray, i);
  1048. if (!get_int(jentry, "index", &net_idx))
  1049. return false;
  1050. keys_add_net_key((uint16_t) net_idx);
  1051. if (!get_int(jentry, "phase", &phase))
  1052. return false;
  1053. keys_set_net_key_phase(net_idx, (uint8_t) phase, false);
  1054. }
  1055. json_object_object_get_ex(jobj, "appKeys", &jarray);
  1056. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1057. return false;
  1058. key_cnt = json_object_array_length(jarray);
  1059. if (key_cnt < 0)
  1060. return false;
  1061. for (i = 0; i < key_cnt; ++i) {
  1062. jentry = json_object_array_get_idx(jarray, i);
  1063. if (!get_int(jentry, "boundNetKey", &net_idx))
  1064. return false;
  1065. if (!get_int(jentry, "index", &app_idx))
  1066. return false;
  1067. keys_add_app_key((uint16_t) net_idx, (uint16_t) app_idx);
  1068. }
  1069. return true;
  1070. }
  1071. bool mesh_db_add_net_key(uint16_t net_idx)
  1072. {
  1073. json_object *jkey, *jarray;
  1074. char buf[12];
  1075. if (!cfg || !cfg->jcfg)
  1076. return false;
  1077. json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
  1078. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1079. return false;
  1080. if (get_key_object(jarray, net_idx))
  1081. return true;
  1082. jkey = json_object_new_object();
  1083. snprintf(buf, 12, "Subnet %4.4x", net_idx);
  1084. if (!add_string(jkey, "name", buf))
  1085. goto fail;
  1086. if (!write_int(jkey, "index", net_idx))
  1087. goto fail;
  1088. if (!write_int(jkey, "phase", KEY_REFRESH_PHASE_NONE))
  1089. goto fail;
  1090. if (!add_string(jkey, "minSecurity", "secure"))
  1091. goto fail;
  1092. if (!set_timestamp(jkey))
  1093. goto fail;
  1094. json_object_array_add(jarray, jkey);
  1095. return save_config();
  1096. fail:
  1097. json_object_put(jkey);
  1098. return false;
  1099. }
  1100. bool mesh_db_del_net_key(uint16_t net_idx)
  1101. {
  1102. if (!cfg || !cfg->jcfg)
  1103. return false;
  1104. return delete_key(cfg->jcfg, "netKeys", net_idx);
  1105. }
  1106. bool mesh_db_set_net_key_phase(uint16_t net_idx, uint8_t phase)
  1107. {
  1108. json_object *jval, *jarray, *jkey;
  1109. if (!cfg || !cfg->jcfg)
  1110. return false;
  1111. json_object_object_get_ex(cfg->jcfg, "netKeys", &jarray);
  1112. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1113. return false;
  1114. jkey = get_key_object(jarray, net_idx);
  1115. if (!jkey)
  1116. return false;
  1117. jval = json_object_new_int(phase);
  1118. if (!jval)
  1119. return false;
  1120. json_object_object_add(jkey, "phase", jval);
  1121. return save_config();
  1122. }
  1123. bool mesh_db_add_app_key(uint16_t net_idx, uint16_t app_idx)
  1124. {
  1125. if (!cfg || !cfg->jcfg)
  1126. return false;
  1127. if (!add_app_key(cfg->jcfg, net_idx, app_idx))
  1128. return false;
  1129. return save_config();
  1130. }
  1131. bool mesh_db_del_app_key(uint16_t app_idx)
  1132. {
  1133. if (!cfg || !cfg->jcfg)
  1134. return false;
  1135. return delete_key(cfg->jcfg, "appKeys", app_idx);
  1136. }
  1137. bool mesh_db_add_group(struct mesh_group *grp)
  1138. {
  1139. json_object *jgroup, *jgroups, *jval;
  1140. char buf[16];
  1141. if (!cfg || !cfg->jcfg)
  1142. return false;
  1143. if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups))
  1144. return false;
  1145. jgroup = json_object_new_object();
  1146. if (!jgroup)
  1147. return false;
  1148. snprintf(buf, 11, "Group_%4.4x", grp->addr);
  1149. jval = json_object_new_string(buf);
  1150. json_object_object_add(jgroup, "name", jval);
  1151. if (IS_VIRTUAL(grp->addr)) {
  1152. if (!add_u8_16(jgroup, "address", grp->label))
  1153. goto fail;
  1154. } else {
  1155. if (!write_uint16_hex(jgroup, "address", grp->addr))
  1156. goto fail;
  1157. }
  1158. /* Initialize parent group to unassigned address for now*/
  1159. if (!write_uint16_hex(jgroup, "parentAddress", UNASSIGNED_ADDRESS))
  1160. goto fail;
  1161. json_object_array_add(jgroups, jgroup);
  1162. return save_config();
  1163. fail:
  1164. json_object_put(jgroup);
  1165. return false;
  1166. }
  1167. struct l_queue *mesh_db_load_groups(void)
  1168. {
  1169. json_object *jgroups;
  1170. struct l_queue *groups;
  1171. int i, sz;
  1172. if (!cfg || !cfg->jcfg)
  1173. return NULL;
  1174. if (!json_object_object_get_ex(cfg->jcfg, "groups", &jgroups)) {
  1175. jgroups = json_object_new_array();
  1176. if (!jgroups)
  1177. return NULL;
  1178. json_object_object_add(cfg->jcfg, "groups", jgroups);
  1179. }
  1180. groups = l_queue_new();
  1181. sz = json_object_array_length(jgroups);
  1182. for (i = 0; i < sz; ++i) {
  1183. json_object *jgroup, *jval;
  1184. struct mesh_group *grp;
  1185. uint16_t addr, addr_len;
  1186. const char *str;
  1187. jgroup = json_object_array_get_idx(jgroups, i);
  1188. if (!jgroup)
  1189. continue;
  1190. if (!json_object_object_get_ex(jgroup, "name", &jval))
  1191. continue;
  1192. str = json_object_get_string(jval);
  1193. if (strlen(str) != 10)
  1194. continue;
  1195. if (sscanf(str + 6, "%04hx", &addr) != 1)
  1196. continue;
  1197. if (!json_object_object_get_ex(jgroup, "address", &jval))
  1198. continue;
  1199. str = json_object_get_string(jval);
  1200. addr_len = strlen(str);
  1201. if (addr_len != 4 && addr_len != 32)
  1202. continue;
  1203. if (addr_len == 32 && !IS_VIRTUAL(addr))
  1204. continue;
  1205. grp = l_new(struct mesh_group, 1);
  1206. if (addr_len == 4)
  1207. sscanf(str, "%04hx", &grp->addr);
  1208. else {
  1209. str2hex(str, 32, grp->label, 16);
  1210. grp->addr = addr;
  1211. }
  1212. l_queue_insert(groups, grp, compare_group_addr, NULL);
  1213. }
  1214. return groups;
  1215. }
  1216. static json_object *init_elements(uint8_t num_els)
  1217. {
  1218. json_object *jelements;
  1219. uint8_t i;
  1220. jelements = json_object_new_array();
  1221. for (i = 0; i < num_els; ++i) {
  1222. json_object *jelement, *jmods;
  1223. jelement = json_object_new_object();
  1224. write_int(jelement, "index", i);
  1225. write_uint16_hex(jelement, "location", DEFAULT_LOCATION);
  1226. jmods = json_object_new_array();
  1227. json_object_object_add(jelement, "models", jmods);
  1228. json_object_array_add(jelements, jelement);
  1229. }
  1230. return jelements;
  1231. }
  1232. bool mesh_db_add_node(uint8_t uuid[16], uint8_t num_els, uint16_t unicast,
  1233. uint16_t net_idx)
  1234. {
  1235. json_object *jnode;
  1236. json_object *jelements, *jnodes, *jnetkeys, *jappkeys;
  1237. char buf[37];
  1238. if (!cfg || !cfg->jcfg)
  1239. return false;
  1240. jnode = get_node_by_uuid(cfg->jcfg, uuid);
  1241. if (jnode) {
  1242. l_error("Node already exists");
  1243. return false;
  1244. }
  1245. jnode = json_object_new_object();
  1246. if (!jnode)
  1247. return false;
  1248. if (!l_uuid_to_string(uuid, buf, sizeof(buf)))
  1249. goto fail;
  1250. if (!add_string(jnode, "UUID", buf))
  1251. goto fail;
  1252. if (!add_string(jnode, "security", "secure"))
  1253. goto fail;
  1254. if (!write_bool(jnode, "excluded", false))
  1255. goto fail;
  1256. if (!write_bool(jnode, "configComplete", false))
  1257. goto fail;
  1258. jelements = init_elements(num_els);
  1259. json_object_object_add(jnode, "elements", jelements);
  1260. jnetkeys = json_object_new_array();
  1261. if (!jnetkeys)
  1262. goto fail;
  1263. json_object_object_add(jnode, "netKeys", jnetkeys);
  1264. if (!add_node_key(jnode, "netKeys", net_idx))
  1265. goto fail;
  1266. jappkeys = json_object_new_array();
  1267. if (!jappkeys)
  1268. goto fail;
  1269. json_object_object_add(jnode, "appKeys", jappkeys);
  1270. if (!write_uint16_hex(jnode, "unicastAddress", unicast))
  1271. goto fail;
  1272. if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jnodes))
  1273. goto fail;
  1274. json_object_array_add(jnodes, jnode);
  1275. return save_config();
  1276. fail:
  1277. json_object_put(jnode);
  1278. return false;
  1279. }
  1280. bool mesh_db_del_node(uint16_t unicast)
  1281. {
  1282. json_object *jarray;
  1283. int i, sz;
  1284. if (!json_object_object_get_ex(cfg->jcfg, "nodes", &jarray))
  1285. return false;
  1286. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1287. return false;
  1288. sz = json_object_array_length(jarray);
  1289. for (i = 0; i < sz; ++i) {
  1290. json_object *jentry, *jval;
  1291. uint16_t addr;
  1292. const char *str;
  1293. jentry = json_object_array_get_idx(jarray, i);
  1294. if (!json_object_object_get_ex(jentry, "unicastAddress",
  1295. &jval))
  1296. continue;
  1297. str = json_object_get_string(jval);
  1298. if (sscanf(str, "%04hx", &addr) != 1)
  1299. continue;
  1300. if (addr == unicast)
  1301. break;
  1302. }
  1303. if (i == sz)
  1304. return true;
  1305. json_object_array_del_idx(jarray, i, 1);
  1306. return save_config();
  1307. }
  1308. static json_object *init_model(uint16_t mod_id)
  1309. {
  1310. json_object *jmod, *jarray;
  1311. jmod = json_object_new_object();
  1312. if (!write_uint16_hex(jmod, "modelId", mod_id)) {
  1313. json_object_put(jmod);
  1314. return NULL;
  1315. }
  1316. jarray = json_object_new_array();
  1317. json_object_object_add(jmod, "bind", jarray);
  1318. jarray = json_object_new_array();
  1319. json_object_object_add(jmod, "subscribe", jarray);
  1320. return jmod;
  1321. }
  1322. static json_object *init_vendor_model(uint32_t mod_id)
  1323. {
  1324. json_object *jmod, *jarray;
  1325. jmod = json_object_new_object();
  1326. if (!write_uint32_hex(jmod, "modelId", mod_id)) {
  1327. json_object_put(jmod);
  1328. return NULL;
  1329. }
  1330. jarray = json_object_new_array();
  1331. json_object_object_add(jmod, "bind", jarray);
  1332. jarray = json_object_new_array();
  1333. json_object_object_add(jmod, "subscribe", jarray);
  1334. return jmod;
  1335. }
  1336. bool mesh_db_node_set_composition(uint16_t unicast, uint8_t *data, uint16_t len)
  1337. {
  1338. uint16_t features;
  1339. int sz, i = 0;
  1340. json_object *jnode, *jobj, *jelements;
  1341. uint16_t crpl;
  1342. if (!cfg || !cfg->jcfg)
  1343. return false;
  1344. jnode = get_node_by_unicast(cfg->jcfg, unicast);
  1345. if (!jnode)
  1346. return false;
  1347. /* skip page -- We only support Page Zero */
  1348. data++;
  1349. len--;
  1350. /* If "crpl" property is present, composition is already recorded */
  1351. if (json_object_object_get_ex(jnode, "crpl", &jobj))
  1352. return true;
  1353. if (!write_uint16_hex(jnode, "cid", l_get_le16(&data[0])))
  1354. return false;
  1355. if (!write_uint16_hex(jnode, "pid", l_get_le16(&data[2])))
  1356. return false;
  1357. if (!write_uint16_hex(jnode, "vid", l_get_le16(&data[4])))
  1358. return false;
  1359. crpl = l_get_le16(&data[6]);
  1360. features = l_get_le16(&data[8]);
  1361. data += 10;
  1362. len -= 10;
  1363. jobj = json_object_object_get(jnode, "features");
  1364. if (!jobj) {
  1365. jobj = json_object_new_object();
  1366. json_object_object_add(jnode, "features", jobj);
  1367. }
  1368. if (!(features & FEATURE_RELAY))
  1369. write_int(jobj, "relay", 2);
  1370. if (!(features & FEATURE_FRIEND))
  1371. write_int(jobj, "friend", 2);
  1372. if (!(features & FEATURE_PROXY))
  1373. write_int(jobj, "proxy", 2);
  1374. if (!(features & FEATURE_LPN))
  1375. write_int(jobj, "lowPower", 2);
  1376. jelements = json_object_object_get(jnode, "elements");
  1377. if (!jelements)
  1378. return false;
  1379. sz = json_object_array_length(jelements);
  1380. while (len) {
  1381. json_object *jentry, *jmods;
  1382. uint32_t mod_id;
  1383. uint8_t m, v;
  1384. /* Mismatch in the element count */
  1385. if (i >= sz)
  1386. return false;
  1387. jentry = json_object_array_get_idx(jelements, i);
  1388. write_int(jentry, "index", i);
  1389. if (!write_uint16_hex(jentry, "location", l_get_le16(data)))
  1390. return false;
  1391. data += 2;
  1392. len -= 2;
  1393. m = *data++;
  1394. v = *data++;
  1395. len -= 2;
  1396. jmods = json_object_object_get(jentry, "models");
  1397. if (!jmods) {
  1398. /* For backwards compatibility */
  1399. jmods = json_object_new_array();
  1400. json_object_object_add(jentry, "models", jmods);
  1401. }
  1402. while (len >= 2 && m--) {
  1403. mod_id = l_get_le16(data);
  1404. jobj = init_model(mod_id);
  1405. if (!jobj)
  1406. goto fail;
  1407. json_object_array_add(jmods, jobj);
  1408. data += 2;
  1409. len -= 2;
  1410. }
  1411. while (len >= 4 && v--) {
  1412. jobj = json_object_new_object();
  1413. mod_id = l_get_le16(data + 2);
  1414. mod_id = l_get_le16(data) << 16 | mod_id;
  1415. jobj = init_vendor_model(mod_id);
  1416. if (!jobj)
  1417. goto fail;
  1418. json_object_array_add(jmods, jobj);
  1419. data += 4;
  1420. len -= 4;
  1421. }
  1422. i++;
  1423. }
  1424. /* CRPL is written last. Will be used to check composition's presence */
  1425. if (!write_uint16_hex(jnode, "crpl", crpl))
  1426. goto fail;
  1427. /* Initiate remote's composition from storage */
  1428. if (!load_composition(jnode, unicast))
  1429. goto fail;
  1430. return save_config();
  1431. fail:
  1432. /* Reset elements array */
  1433. json_object_object_del(jnode, "elements");
  1434. init_elements(sz);
  1435. return false;
  1436. }
  1437. bool mesh_db_get_token(uint8_t token[8])
  1438. {
  1439. if (!cfg || !cfg->jcfg)
  1440. return false;
  1441. memcpy(token, cfg->token, 8);
  1442. return true;
  1443. }
  1444. bool mesh_db_get_addr_range(uint16_t *low, uint16_t *high)
  1445. {
  1446. json_object *jprov, *jarray, *jobj, *jlow, *jhigh;
  1447. const char *str;
  1448. if (!cfg || !cfg->jcfg)
  1449. return false;
  1450. jarray = json_object_object_get(cfg->jcfg, "provisioniers");
  1451. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1452. return false;
  1453. /* Assumption: only one provisioner in the system */
  1454. jprov = json_object_array_get_idx(jarray, 0);
  1455. if (!jprov)
  1456. return false;
  1457. if (!json_object_object_get_ex(jprov, "allocatedUnicastRange", &jarray))
  1458. return false;
  1459. /* Assumption: only one contiguous range is specified */
  1460. jobj = json_object_array_get_idx(jarray, 0);
  1461. if (!jobj)
  1462. return false;
  1463. if (!json_object_object_get_ex(jobj, "lowAddress", &jlow) ||
  1464. !json_object_object_get_ex(jobj, "highAddress", &jhigh))
  1465. return false;
  1466. str = json_object_get_string(jlow);
  1467. if (sscanf(str, "%04hx", low) != 1)
  1468. return false;
  1469. str = json_object_get_string(jhigh);
  1470. if (sscanf(str, "%04hx", high) != 1)
  1471. return false;
  1472. return true;
  1473. }
  1474. /*
  1475. * This is a simplistic implementation onf allocated range, where
  1476. * the range is one contiguous chunk of the address space.
  1477. */
  1478. static bool add_range(json_object *jobj, const char *keyword, uint16_t low,
  1479. uint16_t high)
  1480. {
  1481. json_object *jarray, *jrange;
  1482. jrange = json_object_new_object();
  1483. if (!write_uint16_hex(jrange, "lowAddress", low))
  1484. goto fail;
  1485. if (!write_uint16_hex(jrange, "highAddress", high))
  1486. goto fail;
  1487. jarray = json_object_new_array();
  1488. if (!jarray)
  1489. goto fail;
  1490. json_object_array_add(jarray, jrange);
  1491. json_object_object_add(jobj, keyword, jarray);
  1492. return true;
  1493. fail:
  1494. json_object_put(jrange);
  1495. return false;
  1496. }
  1497. bool mesh_db_add_provisioner(const char *name, uint8_t uuid[16],
  1498. uint16_t unicast_low, uint16_t unicast_high,
  1499. uint16_t group_low, uint16_t group_high)
  1500. {
  1501. json_object *jprovs, *jprov, *jscenes;
  1502. char buf[37];
  1503. if (!cfg || !cfg->jcfg)
  1504. return false;
  1505. if (!json_object_object_get_ex(cfg->jcfg, "provisioners", &jprovs))
  1506. return false;
  1507. if (!jprovs || json_object_get_type(jprovs) != json_type_array)
  1508. return false;
  1509. jprov = json_object_new_object();
  1510. if (!add_string(jprov, "provisionerName", name))
  1511. goto fail;
  1512. if (!l_uuid_to_string(uuid, buf, sizeof(buf)))
  1513. goto fail;
  1514. if (!add_string(jprov, "UUID", buf))
  1515. goto fail;
  1516. if (!add_range(jprov, "allocatedUnicastRange", unicast_low,
  1517. unicast_high))
  1518. goto fail;
  1519. if (!add_range(jprov, "allocatedGroupRange", group_low, group_high))
  1520. goto fail;
  1521. /* Scenes are not supported. Just add an empty array */
  1522. jscenes = json_object_new_array();
  1523. if (!jscenes)
  1524. goto fail;
  1525. json_object_object_add(jprov, "allocatedSceneRange", jscenes);
  1526. json_object_array_add(jprovs, jprov);
  1527. return save_config();
  1528. fail:
  1529. json_object_put(jprov);
  1530. return false;
  1531. }
  1532. uint32_t mesh_db_get_iv_index(void)
  1533. {
  1534. int ivi;
  1535. if (!cfg || !cfg->jcfg)
  1536. return 0;
  1537. if (!get_int(cfg->jcfg, "ivIndex", &ivi))
  1538. return 0;
  1539. return (uint32_t) ivi;
  1540. }
  1541. bool mesh_db_set_iv_index(uint32_t ivi)
  1542. {
  1543. if (!cfg || !cfg->jcfg)
  1544. return false;
  1545. write_int(cfg->jcfg, "ivIndex", ivi);
  1546. return save_config();
  1547. }
  1548. static int get_rejected_by_iv_index(json_object *jarray, uint32_t iv_index)
  1549. {
  1550. int i, cnt;
  1551. cnt = json_object_array_length(jarray);
  1552. for (i = 0; i < cnt; i++) {
  1553. json_object *jentry;
  1554. int index;
  1555. jentry = json_object_array_get_idx(jarray, i);
  1556. if (!get_int(jentry, "ivIndex", &index))
  1557. continue;
  1558. if (iv_index == (uint32_t)index)
  1559. return i;
  1560. }
  1561. return -1;
  1562. }
  1563. static bool load_rejected_addresses(json_object *jobj)
  1564. {
  1565. json_object *jarray;
  1566. int i, cnt;
  1567. json_object_object_get_ex(jobj, "networkExclusions", &jarray);
  1568. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1569. return true;
  1570. cnt = json_object_array_length(jarray);
  1571. for (i = 0; i < cnt; i++) {
  1572. json_object *jaddrs, *jentry, *jval;
  1573. int iv_index, addr_cnt, j;
  1574. jentry = json_object_array_get_idx(jarray, i);
  1575. if (!get_int(jentry, "ivIndex", &iv_index))
  1576. return false;
  1577. if (!json_object_object_get_ex(jentry, "addresses",
  1578. &jaddrs))
  1579. return false;
  1580. addr_cnt = json_object_array_length(jaddrs);
  1581. for (j = 0; j < addr_cnt; j++) {
  1582. const char *str;
  1583. uint16_t unicast;
  1584. jval = json_object_array_get_idx(jaddrs, j);
  1585. str = json_object_get_string(jval);
  1586. if (sscanf(str, "%04hx", &unicast) != 1)
  1587. return false;
  1588. remote_add_rejected_address(unicast, iv_index, false);
  1589. }
  1590. }
  1591. return true;
  1592. }
  1593. bool mesh_db_add_rejected_addr(uint16_t unicast, uint32_t iv_index)
  1594. {
  1595. json_object *jarray, *jobj, *jaddrs, *jstring;
  1596. int idx;
  1597. char buf[5];
  1598. if (!cfg || !cfg->jcfg)
  1599. return false;
  1600. json_object_object_get_ex(cfg->jcfg, "networkExclusions", &jarray);
  1601. if (!jarray) {
  1602. jarray = json_object_new_array();
  1603. json_object_object_add(cfg->jcfg, "networkExclusions", jarray);
  1604. }
  1605. idx = get_rejected_by_iv_index(jarray, iv_index);
  1606. if (idx < 0) {
  1607. jobj = json_object_new_object();
  1608. if (!write_int(jobj, "ivIndex", iv_index))
  1609. goto fail;
  1610. jaddrs = json_object_new_array();
  1611. json_object_object_add(jobj, "addresses", jaddrs);
  1612. } else {
  1613. jobj = json_object_array_get_idx(jarray, idx);
  1614. }
  1615. json_object_object_get_ex(jobj, "addresses", &jaddrs);
  1616. snprintf(buf, 5, "%4.4x", unicast);
  1617. jstring = json_object_new_string(buf);
  1618. if (!jstring)
  1619. goto fail;
  1620. json_object_array_add(jaddrs, jstring);
  1621. if (idx < 0)
  1622. json_object_array_add(jarray, jobj);
  1623. return save_config();
  1624. fail:
  1625. json_object_put(jobj);
  1626. return false;
  1627. }
  1628. bool mesh_db_clear_rejected(uint32_t iv_index)
  1629. {
  1630. json_object *jarray;
  1631. int idx;
  1632. if (!cfg || !cfg->jcfg)
  1633. return false;
  1634. json_object_object_get_ex(cfg->jcfg, "networkExclusions", &jarray);
  1635. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1636. return false;
  1637. idx = get_rejected_by_iv_index(jarray, iv_index);
  1638. if (idx < 0)
  1639. return true;
  1640. json_object_array_del_idx(jarray, idx, 1);
  1641. return save_config();
  1642. }
  1643. bool mesh_db_create(const char *fname, const uint8_t token[8],
  1644. const char *mesh_name)
  1645. {
  1646. json_object *jcfg, *jarray;
  1647. uint8_t uuid[16];
  1648. char buf[37];
  1649. if (cfg)
  1650. return false;
  1651. if (!fname)
  1652. return false;
  1653. jcfg = json_object_new_object();
  1654. if (!jcfg)
  1655. return false;
  1656. cfg = l_new(struct mesh_db, 1);
  1657. cfg->jcfg = jcfg;
  1658. cfg->cfg_fname = l_strdup(fname);
  1659. memcpy(cfg->token, token, 8);
  1660. if (!add_u8_8(jcfg, "token", token))
  1661. goto fail;
  1662. l_uuid_v4(uuid);
  1663. if (!l_uuid_to_string(uuid, buf, sizeof(buf)))
  1664. goto fail;
  1665. if (!add_string(jcfg, "meshUUID", buf))
  1666. goto fail;
  1667. if (mesh_name && !add_string(jcfg, "meshName", mesh_name))
  1668. goto fail;
  1669. jarray = json_object_new_array();
  1670. if (!jarray)
  1671. goto fail;
  1672. json_object_object_add(jcfg, "nodes", jarray);
  1673. jarray = json_object_new_array();
  1674. if (!jarray)
  1675. goto fail;
  1676. json_object_object_add(jcfg, "provisioners", jarray);
  1677. jarray = json_object_new_array();
  1678. if (!jarray)
  1679. goto fail;
  1680. json_object_object_add(jcfg, "netKeys", jarray);
  1681. jarray = json_object_new_array();
  1682. if (!jarray)
  1683. goto fail;
  1684. json_object_object_add(jcfg, "appKeys", jarray);
  1685. jarray = json_object_new_array();
  1686. if (!jarray)
  1687. goto fail;
  1688. json_object_object_add(jcfg, "networkExclusions", jarray);
  1689. write_int(jcfg, "ivIndex", 0);
  1690. if (!save_config())
  1691. goto fail;
  1692. return true;
  1693. fail:
  1694. release_config();
  1695. return false;
  1696. }
  1697. bool mesh_db_load(const char *fname)
  1698. {
  1699. int fd;
  1700. char *str;
  1701. struct stat st;
  1702. ssize_t sz;
  1703. json_object *jcfg;
  1704. fd = open(fname, O_RDONLY);
  1705. if (fd < 0)
  1706. return false;
  1707. if (fstat(fd, &st) == -1) {
  1708. close(fd);
  1709. return false;
  1710. }
  1711. str = (char *) l_new(char, st.st_size + 1);
  1712. if (!str) {
  1713. close(fd);
  1714. return false;
  1715. }
  1716. sz = read(fd, str, st.st_size);
  1717. if (sz != st.st_size) {
  1718. l_error("Failed to read configuration file %s", fname);
  1719. return false;
  1720. }
  1721. jcfg = json_tokener_parse(str);
  1722. close(fd);
  1723. l_free(str);
  1724. if (!jcfg)
  1725. return false;
  1726. cfg = l_new(struct mesh_db, 1);
  1727. cfg->jcfg = jcfg;
  1728. cfg->cfg_fname = l_strdup(fname);
  1729. if (!get_token(jcfg, cfg->token)) {
  1730. l_error("Configuration file missing token");
  1731. goto fail;
  1732. }
  1733. if (!load_keys(jcfg))
  1734. goto fail;
  1735. load_remotes(jcfg);
  1736. load_rejected_addresses(jcfg);
  1737. return true;
  1738. fail:
  1739. release_config();
  1740. return false;
  1741. }
  1742. bool mesh_db_set_device_key(void *expt_cfg, uint16_t unicast, uint8_t key[16])
  1743. {
  1744. json_object *jnode;
  1745. if (!expt_cfg)
  1746. return false;
  1747. jnode = get_node_by_unicast(expt_cfg, unicast);
  1748. if (!jnode)
  1749. return false;
  1750. return add_u8_16(jnode, "deviceKey", key);
  1751. }
  1752. bool mesh_db_set_net_key(void *expt_cfg, uint16_t idx, uint8_t key[16],
  1753. uint8_t *old_key, uint8_t phase)
  1754. {
  1755. json_object *jarray, *jkey;
  1756. if (!expt_cfg)
  1757. return false;
  1758. json_object_object_get_ex(expt_cfg, "netKeys", &jarray);
  1759. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1760. return false;
  1761. jkey = get_key_object(jarray, idx);
  1762. if (!jkey)
  1763. return false;
  1764. if (!write_int(jkey, "phase", phase))
  1765. return false;
  1766. if (!add_u8_16(jkey, "key", key))
  1767. return false;
  1768. if (old_key && !(!add_u8_16(jkey, "oldKey", old_key)))
  1769. return false;
  1770. return true;
  1771. }
  1772. bool mesh_db_set_app_key(void *expt_cfg, uint16_t net_idx, uint16_t app_idx,
  1773. uint8_t key[16], uint8_t *old_key)
  1774. {
  1775. json_object *jarray, *jkey;
  1776. if (!expt_cfg)
  1777. return false;
  1778. json_object_object_get_ex(expt_cfg, "appKeys", &jarray);
  1779. if (!jarray || json_object_get_type(jarray) != json_type_array)
  1780. return false;
  1781. jkey = get_key_object(jarray, app_idx);
  1782. if (!jkey)
  1783. return false;
  1784. if (!add_u8_16(jkey, "key", key))
  1785. return false;
  1786. if (old_key && !(!add_u8_16(jkey, "oldKey", old_key)))
  1787. return false;
  1788. return true;
  1789. }
  1790. void *mesh_db_prepare_export(void)
  1791. {
  1792. json_object *export = NULL, *jarray;
  1793. if (!cfg || !cfg->jcfg)
  1794. return false;
  1795. if (json_object_deep_copy(cfg->jcfg, &export, NULL) != 0)
  1796. return NULL;
  1797. /* Delete token */
  1798. json_object_object_del(export, "token");
  1799. /* Delete IV index */
  1800. json_object_object_del(export, "ivIndex");
  1801. /* Scenes are not supported. Just add an empty array */
  1802. jarray = json_object_new_array();
  1803. json_object_object_add(export, "scenes", jarray);
  1804. if (!write_bool(export, "partial", false))
  1805. l_warn("Failed to write\"partial\" property");
  1806. return export;
  1807. }
  1808. bool mesh_db_finish_export(bool is_error, void *expt_cfg, const char *fname)
  1809. {
  1810. FILE *outfile = NULL;
  1811. const char *str, *hdr;
  1812. json_object *jhdr = NULL;
  1813. bool result = false;
  1814. char *pos;
  1815. uint32_t sz;
  1816. if (!expt_cfg)
  1817. return false;
  1818. if (is_error) {
  1819. json_object_put(expt_cfg);
  1820. return true;
  1821. }
  1822. if (!fname)
  1823. goto done;
  1824. outfile = fopen(fname, "w");
  1825. if (!outfile) {
  1826. l_error("Failed to save configuration to %s", fname);
  1827. goto done;
  1828. }
  1829. jhdr = json_object_new_object();
  1830. if (!add_string(jhdr, "$schema", js_schema))
  1831. goto done;
  1832. if (!add_string(jhdr, "id", schema_id))
  1833. goto done;
  1834. if (!add_string(jhdr, "version", schema_version))
  1835. goto done;
  1836. hdr = json_object_to_json_string_ext(jhdr, JSON_C_TO_STRING_PRETTY |
  1837. JSON_C_TO_STRING_NOSLASHESCAPE);
  1838. str = json_object_to_json_string_ext(expt_cfg, JSON_C_TO_STRING_PRETTY |
  1839. JSON_C_TO_STRING_NOSLASHESCAPE);
  1840. if (!hdr || !str)
  1841. goto done;
  1842. /*
  1843. * Write two strings to the output while stripping closing "}" from the
  1844. * header string and opening "{" from the config object.
  1845. */
  1846. pos = strrchr(hdr, '}');
  1847. if (!pos)
  1848. goto done;
  1849. *pos = '\0';
  1850. pos = strrchr(hdr, '"');
  1851. if (!pos)
  1852. goto done;
  1853. pos[1] = ',';
  1854. if (fwrite(hdr, sizeof(char), strlen(hdr), outfile) < strlen(hdr))
  1855. goto done;
  1856. pos = strchr(str, '{');
  1857. if (!pos || pos[1] == '\0')
  1858. goto done;
  1859. pos++;
  1860. sz = strlen(pos);
  1861. if (fwrite(pos, sizeof(char), sz, outfile) < sz)
  1862. goto done;
  1863. result = true;
  1864. done:
  1865. if (outfile)
  1866. fclose(outfile);
  1867. json_object_put(expt_cfg);
  1868. if (jhdr)
  1869. json_object_put(jhdr);
  1870. return result;
  1871. }