| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2017 Intel Corporation. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <errno.h>
- #include <fcntl.h>
- #include <glib.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <json-c/json.h>
- #include <sys/stat.h>
- #include <glib.h>
- #include "src/shared/util.h"
- #include "src/shared/shell.h"
- #include "tools/mesh-gatt/mesh-net.h"
- #include "tools/mesh-gatt/crypto.h"
- #include "tools/mesh-gatt/keys.h"
- #include "tools/mesh-gatt/net.h"
- #include "tools/mesh-gatt/node.h"
- #include "tools/mesh-gatt/util.h"
- #include "tools/mesh-gatt/prov-db.h"
- #define CHECK_KEY_IDX_RANGE(x) (((x) >= 0) && ((x) <= 4095))
- static const char *prov_filename;
- static const char *local_filename;
- static char* prov_file_read(const char *filename)
- {
- int fd;
- char *str;
- struct stat st;
- ssize_t sz;
- if (!filename)
- return NULL;
- fd = open(filename,O_RDONLY);
- if (!fd)
- return NULL;
- if (fstat(fd, &st) == -1) {
- close(fd);
- return NULL;
- }
- str = (char *) g_malloc0(st.st_size + 1);
- if (!str) {
- close(fd);
- return NULL;
- }
- sz = read(fd, str, st.st_size);
- if (sz != st.st_size)
- bt_shell_printf("Incomplete read: %d vs %d\n", (int)sz,
- (int)(st.st_size));
- close(fd);
- return str;
- }
- static void prov_file_write(json_object *jmain, bool local)
- {
- FILE *outfile;
- const char *out_str;
- const char *out_filename;
- if (local)
- out_filename = local_filename;
- else
- out_filename = prov_filename;
- outfile = fopen(out_filename, "wr");
- if (!outfile) {
- bt_shell_printf("Failed to open file %s for writing\n", out_filename);
- return;
- }
- out_str = json_object_to_json_string_ext(jmain,
- JSON_C_TO_STRING_PRETTY);
- fwrite(out_str, sizeof(char), strlen(out_str), outfile);
- fclose(outfile);
- }
- static void put_uint16(json_object *jobject, const char *desc, uint16_t value)
- {
- json_object *jstring;
- char buf[5];
- snprintf(buf, 5, "%4.4x", value);
- jstring = json_object_new_string(buf);
- json_object_object_add(jobject, desc, jstring);
- }
- static void put_uint32(json_object *jobject, const char *desc, uint32_t value)
- {
- json_object *jstring;
- char buf[9];
- snprintf(buf, 9, "%8.8x", value);
- jstring = json_object_new_string(buf);
- json_object_object_add(jobject, desc, jstring);
- }
- static void put_uint16_array_entry(json_object *jarray, uint16_t value)
- {
- json_object *jstring;
- char buf[5];
- snprintf(buf, 5, "%4.4x", value);
- jstring = json_object_new_string(buf);
- json_object_array_add(jarray, jstring);
- }
- static void put_uint32_array_entry(json_object *jarray, uint32_t value)
- {
- json_object *jstring;
- char buf[9];
- snprintf(buf, 9, "%8.8x", value);
- jstring = json_object_new_string(buf);
- json_object_array_add(jarray, jstring);
- }
- static void put_uint16_list(json_object *jarray, GList *list)
- {
- GList *l;
- if (!list)
- return;
- for (l = list; l; l = l->next) {
- uint32_t ivalue = GPOINTER_TO_UINT(l->data);
- put_uint16_array_entry(jarray, ivalue);
- }
- }
- static void add_node_idxs(json_object *jnode, const char *desc,
- GList *idxs)
- {
- json_object *jarray;
- jarray = json_object_new_array();
- put_uint16_list(jarray, idxs);
- json_object_object_add(jnode, desc, jarray);
- }
- static bool parse_unicast_range(json_object *jobject)
- {
- int cnt;
- int i;
- cnt = json_object_array_length(jobject);
- for (i = 0; i < cnt; ++i) {
- json_object *jrange;
- json_object *jvalue;
- uint16_t low, high;
- char *str;
- jrange = json_object_array_get_idx(jobject, i);
- json_object_object_get_ex(jrange, "lowAddress", &jvalue);
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &low) != 1)
- return false;
- json_object_object_get_ex(jrange, "highAddress", &jvalue);
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &high) != 1)
- return false;
- if(high < low)
- return false;
- net_add_address_pool(low, high);
- }
- return true;
- }
- static int parse_node_keys(struct mesh_node *node, json_object *jidxs,
- bool is_app_key)
- {
- int idx_cnt;
- int i;
- idx_cnt = json_object_array_length(jidxs);
- for (i = 0; i < idx_cnt; ++i) {
- int idx;
- json_object *jvalue;
- jvalue = json_object_array_get_idx(jidxs, i);
- if (!jvalue)
- break;
- idx = json_object_get_int(jvalue);
- if (!CHECK_KEY_IDX_RANGE(idx))
- break;
- if (is_app_key)
- node_app_key_add(node, idx);
- else
- node_net_key_add(node, idx);
- }
- return i;
- }
- static bool parse_composition_models(struct mesh_node *node, int index,
- json_object *jmodels)
- {
- int model_cnt;
- int i;
- model_cnt = json_object_array_length(jmodels);
- for (i = 0; i < model_cnt; ++i) {
- json_object *jmodel;
- char *str;
- uint32_t model_id;
- int len;
- jmodel = json_object_array_get_idx(jmodels, i);
- str = (char *)json_object_get_string(jmodel);
- len = strlen(str);
- if (len != 4 && len != 8)
- return false;
- if (sscanf(str, "%08x", &model_id) != 1)
- return false;
- if (len == 4)
- model_id += 0xffff0000;
- node_set_model(node, index, model_id);
- }
- return true;
- }
- static bool parse_composition_elements(struct mesh_node *node,
- json_object *jelements)
- {
- int el_cnt;
- int i;
- el_cnt = json_object_array_length(jelements);
- node_set_num_elements(node, el_cnt);
- for (i = 0; i < el_cnt; ++i) {
- json_object *jelement;
- json_object *jmodels;
- json_object *jvalue;
- int index;
- jelement = json_object_array_get_idx(jelements, i);
- json_object_object_get_ex(jelement, "elementIndex", &jvalue);
- if (jvalue) {
- index = json_object_get_int(jvalue);
- if (index >= el_cnt) {
- return false;
- }
- } else
- return false;
- if (!node_set_element(node, index))
- return false;
- json_object_object_get_ex(jelement, "models", &jmodels);
- if (!jmodels)
- continue;
- if(!parse_composition_models(node, index, jmodels))
- return false;
- }
- return true;
- }
- static bool parse_model_pub(struct mesh_node *node, int ele_idx,
- uint32_t model_id, json_object *jpub)
- {
- json_object *jvalue;
- struct mesh_publication pub;
- char *str;
- memset(&pub, 0, sizeof(struct mesh_publication));
- /* Read only required fields */
- json_object_object_get_ex(jpub, "address", &jvalue);
- if (!jvalue)
- return false;
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &pub.u.addr16) != 1)
- return false;
- json_object_object_get_ex(jpub, "index", &jvalue);
- if (!jvalue)
- return false;
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &pub.app_idx) != 1)
- return false;
- json_object_object_get_ex(jpub, "ttl", &jvalue);
- pub.ttl = json_object_get_int(jvalue);
- if (!node_model_pub_set(node, ele_idx, model_id, &pub))
- return false;
- return true;
- }
- static bool parse_bindings(struct mesh_node *node, int ele_idx,
- uint32_t model_id, json_object *jbindings)
- {
- int cnt;
- int i;
- cnt = json_object_array_length(jbindings);
- for (i = 0; i < cnt; ++i) {
- int key_idx;
- json_object *jvalue;
- jvalue = json_object_array_get_idx(jbindings, i);
- if (!jvalue)
- return true;
- key_idx = json_object_get_int(jvalue);
- if (!CHECK_KEY_IDX_RANGE(key_idx))
- return false;
- if (!node_add_binding(node, ele_idx, model_id, key_idx))
- return false;
- }
- return true;
- }
- static json_object* find_configured_model(struct mesh_node *node, int ele_idx,
- json_object *jmodels, uint32_t target_id)
- {
- int model_cnt;
- int i;
- model_cnt = json_object_array_length(jmodels);
- for (i = 0; i < model_cnt; ++i) {
- json_object *jmodel;
- json_object *jvalue;
- char *str;
- int len;
- uint32_t model_id;
- jmodel = json_object_array_get_idx(jmodels, i);
- json_object_object_get_ex(jmodel, "modelId", &jvalue);
- str = (char *)json_object_get_string(jvalue);
- len = strlen(str);
- if (len != 4 && len != 8)
- return NULL;
- if (sscanf(str, "%08x", &model_id) != 1)
- return NULL;
- if (len == 4)
- model_id += 0xffff0000;
- if (model_id == target_id)
- return jmodel;
- }
- return NULL;
- }
- static bool parse_subscriptions(struct mesh_node *node, int ele_idx,
- uint32_t model_id, json_object *jsubscriptions)
- {
- int cnt;
- int i;
- int addr;
- cnt = json_object_array_length(jsubscriptions);
- for (i = 0; i < cnt; ++i) {
- char *str;
- json_object *jsubscription;
- jsubscription = json_object_array_get_idx(jsubscriptions, i);
- if (!jsubscription)
- return false;
- str = (char *)json_object_get_string(jsubscription);
- if (sscanf(str, "%04x", &addr) != 1)
- return false;
- if (!node_add_subscription(node, ele_idx, model_id, addr))
- return false;
- }
- return true;
- }
- static bool parse_configuration_models(struct mesh_node *node, int ele_idx,
- json_object *jmodels)
- {
- int model_cnt;
- int i;
- model_cnt = json_object_array_length(jmodels);
- for (i = 0; i < model_cnt; ++i) {
- json_object *jmodel;
- json_object *jvalue;
- json_object *jarray;
- char *str;
- int len;
- uint32_t model_id;
- jmodel = json_object_array_get_idx(jmodels, i);
- json_object_object_get_ex(jmodel, "modelId", &jvalue);
- str = (char *)json_object_get_string(jvalue);
- len = strlen(str);
- if (len != 4 && len != 8)
- return false;
- if (sscanf(str, "%08x", &model_id) != 1)
- return false;
- if (len == 4)
- model_id += 0xffff0000;
- json_object_object_get_ex(jmodel, "bind", &jarray);
- if (jarray && !parse_bindings(node, ele_idx, model_id, jarray))
- return false;
- json_object_object_get_ex(jmodel, "subscribe", &jarray);
- if (jarray && !parse_subscriptions(node, ele_idx, model_id, jarray))
- return false;
- json_object_object_get_ex(jmodel, "publish", &jvalue);
- if (jvalue && !parse_model_pub(node, ele_idx, model_id, jvalue))
- return false;
- }
- return true;
- }
- static bool parse_configuration_elements(struct mesh_node *node,
- json_object *jelements, bool local)
- {
- int el_cnt;
- int i;
- el_cnt = json_object_array_length(jelements);
- node_set_num_elements(node, el_cnt);
- for (i = 0; i < el_cnt; ++i) {
- json_object *jelement;
- json_object *jmodels;
- json_object *jvalue;
- int index;
- uint16_t addr;
- jelement = json_object_array_get_idx(jelements, i);
- json_object_object_get_ex(jelement, "elementIndex", &jvalue);
- if (jvalue) {
- index = json_object_get_int(jvalue);
- if (index >= el_cnt) {
- return false;
- }
- } else
- return false;
- if (index == 0) {
- char *str;
- json_object_object_get_ex(jelement, "unicastAddress",
- &jvalue);
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &addr) != 1)
- return false;
- if (!local && !net_reserve_address_range(addr, el_cnt))
- return false;
- node_set_primary(node, addr);
- }
- json_object_object_get_ex(jelement, "models", &jmodels);
- if (!jmodels)
- continue;
- if(!parse_configuration_models(node, index, jmodels))
- return false;
- }
- return true;
- }
- static void add_key(json_object *jobject, const char *desc, uint8_t* key)
- {
- json_object *jstring;
- char hexstr[33];
- hex2str(key, 16, hexstr, 33);
- jstring = json_object_new_string(hexstr);
- json_object_object_add(jobject, desc, jstring);
- }
- static json_object *find_node_by_primary(json_object *jmain, uint16_t primary)
- {
- json_object *jarray;
- int i, len;
- json_object_object_get_ex(jmain, "nodes", &jarray);
- if (!jarray)
- return NULL;
- len = json_object_array_length(jarray);
- for (i = 0; i < len; ++i) {
- json_object *jnode;
- json_object *jconfig;
- json_object *jelements;
- json_object *jelement;
- json_object *jvalue;
- char *str;
- uint16_t addr;
- jnode = json_object_array_get_idx(jarray, i);
- if (!jnode)
- return NULL;
- json_object_object_get_ex(jnode, "configuration", &jconfig);
- if (!jconfig)
- return NULL;
- json_object_object_get_ex(jconfig, "elements", &jelements);
- if (!jelements)
- return NULL;
- jelement = json_object_array_get_idx(jelements, 0);
- if (!jelement)
- return NULL;
- json_object_object_get_ex(jelement, "unicastAddress",
- &jvalue);
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &addr) != 1)
- return NULL;
- if (addr == primary)
- return jnode;
- }
- return NULL;
- }
- void prov_db_print_node_composition(struct mesh_node *node)
- {
- char *in_str;
- const char *comp_str;
- json_object *jmain;
- json_object *jnode;
- json_object *jcomp;
- uint16_t primary = node_get_primary(node);
- const char *filename;
- bool res = false;
- if (!node || !node_get_composition(node))
- return;
- if (node == node_get_local_node())
- filename = local_filename;
- else
- filename = prov_filename;
- in_str = prov_file_read(filename);
- if (!in_str)
- return;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- jnode = find_node_by_primary(jmain, primary);
- if (!jnode)
- goto done;
- json_object_object_get_ex(jnode, "composition", &jcomp);
- if (!jcomp)
- goto done;
- comp_str = json_object_to_json_string_ext(jcomp,
- JSON_C_TO_STRING_PRETTY);
- res = true;
- done:
- if (res)
- bt_shell_printf("\tComposition data for node %4.4x %s\n",
- primary, comp_str);
- else
- bt_shell_printf("\tComposition data for node %4.4x not present\n",
- primary);
- g_free(in_str);
- if (jmain)
- json_object_put(jmain);
- }
- bool prov_db_add_node_composition(struct mesh_node *node, uint8_t *data,
- uint16_t len)
- {
- char *in_str;
- json_object *jmain;
- json_object *jnode;
- json_object *jcomp;
- json_object *jbool;
- json_object *jfeatures;
- json_object *jelements;
- struct mesh_node_composition *comp;
- uint8_t num_ele;
- int i;
- uint16_t primary = node_get_primary(node);
- bool res = NULL;
- comp = node_get_composition(node);
- if (!comp)
- return false;
- in_str = prov_file_read(prov_filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- jnode = find_node_by_primary(jmain, primary);
- if (!jnode)
- goto done;
- jcomp = json_object_new_object();
- put_uint16(jcomp, "cid", comp->cid);
- put_uint16(jcomp, "pid", comp->pid);
- put_uint16(jcomp, "vid", comp->vid);
- put_uint16(jcomp, "crpl", comp->crpl);
- jfeatures = json_object_new_object();
- jbool = json_object_new_boolean(comp->relay);
- json_object_object_add(jfeatures, "relay", jbool);
- jbool = json_object_new_boolean(comp->proxy);
- json_object_object_add(jfeatures, "proxy", jbool);
- jbool = json_object_new_boolean(comp->friend);
- json_object_object_add(jfeatures, "friend", jbool);
- jbool = json_object_new_boolean(comp->lpn);
- json_object_object_add(jfeatures, "lpn", jbool);
- json_object_object_add(jcomp, "features", jfeatures);
- data += 11;
- len -= 11;
- num_ele = node_get_num_elements(node);
- jelements = json_object_new_array();
- for (i = 0; i < num_ele; ++i) {
- json_object *jelement;
- json_object *jmodels;
- json_object *jint;
- uint32_t mod_id;
- uint16_t vendor_id;
- uint8_t m, v;
- jelement = json_object_new_object();
- /* Element Index */
- jint = json_object_new_int(i);
- json_object_object_add(jelement, "elementIndex", jint);
- /* Location */
- put_uint16(jelement, "location", get_le16(data));
- data += 2;
- m = *data++;
- v = *data++;
- len -= 4;
- /* Models */
- jmodels = json_object_new_array();
- while (len >= 2 && m--) {
- mod_id = get_le16(data);
- data += 2;
- len -= 2;
- put_uint16_array_entry(jmodels, (uint16_t) mod_id);
- }
- while (len >= 4 && v--) {
- mod_id = get_le16(data + 2);
- vendor_id = get_le16(data);
- mod_id |= (vendor_id << 16);
- data += 4;
- len -= 4;
- put_uint32_array_entry(jmodels, mod_id);
- }
- json_object_object_add(jelement, "models", jmodels);
- json_object_array_add(jelements, jelement);
- }
- json_object_object_add(jcomp, "elements", jelements);
- json_object_object_add(jnode, "composition", jcomp);
- prov_file_write(jmain, false);
- res = true;;
- done:
- g_free(in_str);
- if(jmain)
- json_object_put(jmain);
- return res;
- }
- bool prov_db_node_set_ttl(struct mesh_node *node, uint8_t ttl)
- {
- char *in_str;
- json_object *jmain;
- json_object *jnode;
- json_object *jconfig;
- json_object *jvalue;
- uint16_t primary = node_get_primary(node);
- const char *filename;
- bool local = node == node_get_local_node();
- bool res = false;
- if (local)
- filename = local_filename;
- else
- filename = prov_filename;
- in_str = prov_file_read(filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- if (local)
- json_object_object_get_ex(jmain, "node", &jnode);
- else
- jnode = find_node_by_primary(jmain, primary);
- if (!jnode)
- goto done;
- json_object_object_get_ex(jnode, "configuration", &jconfig);
- if (!jconfig)
- goto done;
- json_object_object_del(jconfig, "defaultTTL");
- jvalue = json_object_new_int(ttl);
- json_object_object_add(jconfig, "defaultTTL", jvalue);
- prov_file_write(jmain, local);
- res = true;
- done:
- g_free(in_str);
- if(jmain)
- json_object_put(jmain);
- return res;
- }
- static void set_local_iv_index(json_object *jobj, uint32_t idx, bool update)
- {
- json_object *jvalue;
- json_object_object_del(jobj, "IVindex");
- jvalue = json_object_new_int(idx);
- json_object_object_add(jobj, "IVindex", jvalue);
- json_object_object_del(jobj, "IVupdate");
- jvalue = json_object_new_int((update) ? 1 : 0);
- json_object_object_add(jobj, "IVupdate", jvalue);
- }
- bool prov_db_local_set_iv_index(uint32_t iv_index, bool update, bool prov)
- {
- char *in_str;
- json_object *jmain;
- json_object *jnode;
- bool res = false;
- in_str = prov_file_read(local_filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- json_object_object_get_ex(jmain, "node", &jnode);
- set_local_iv_index(jnode, iv_index, update);
- prov_file_write(jmain, true);
- g_free(in_str);
- json_object_put(jmain);
- /* If provisioner, save to global DB as well */
- if (prov) {
- in_str = prov_file_read(prov_filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- set_local_iv_index(jmain, iv_index, update);
- prov_file_write(jmain, false);
- }
- res = true;
- done:
- g_free(in_str);
- if(jmain)
- json_object_put(jmain);
- return res;
- }
- bool prov_db_local_set_seq_num(uint32_t seq_num)
- {
- char *in_str;
- json_object *jmain;
- json_object *jnode;
- json_object *jvalue;
- bool res = false;
- in_str = prov_file_read(local_filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- json_object_object_get_ex(jmain, "node", &jnode);
- json_object_object_del(jnode, "sequenceNumber");
- jvalue = json_object_new_int(seq_num);
- json_object_object_add(jnode, "sequenceNumber", jvalue);
- prov_file_write(jmain, true);
- res = true;
- done:
- g_free(in_str);
- if(jmain)
- json_object_put(jmain);
- return res;
- }
- bool prov_db_node_set_iv_seq(struct mesh_node *node, uint32_t iv, uint32_t seq)
- {
- char *in_str;
- json_object *jmain;
- json_object *jnode;
- json_object *jvalue;
- uint16_t primary = node_get_primary(node);
- bool res = false;
- in_str = prov_file_read(prov_filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- jnode = find_node_by_primary(jmain, primary);
- if (!jnode)
- goto done;
- json_object_object_del(jnode, "IVindex");
- jvalue = json_object_new_int(iv);
- json_object_object_add(jnode, "IVindex", jvalue);
- json_object_object_del(jnode, "sequenceNumber");
- jvalue = json_object_new_int(seq);
- json_object_object_add(jnode, "sequenceNumber", jvalue);
- prov_file_write(jmain, false);
- res = true;
- done:
- g_free(in_str);
- if(jmain)
- json_object_put(jmain);
- return res;
- }
- bool prov_db_node_keys(struct mesh_node *node, GList *idxs, const char *desc)
- {
- char *in_str;
- json_object *jmain;
- json_object *jnode;
- json_object *jconfig;
- json_object *jidxs;
- uint16_t primary = node_get_primary(node);
- const char *filename;
- bool local = (node == node_get_local_node());
- bool res = false;
- if (local)
- filename = local_filename;
- else
- filename = prov_filename;
- in_str = prov_file_read(filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- jnode = find_node_by_primary(jmain, primary);
- if (!jnode)
- goto done;
- json_object_object_get_ex(jnode, "configuration", &jconfig);
- if (!jconfig)
- goto done;
- json_object_object_del(jconfig, desc);
- if (idxs) {
- jidxs = json_object_new_array();
- put_uint16_list(jidxs, idxs);
- json_object_object_add(jconfig, desc, jidxs);
- }
- prov_file_write(jmain, local);
- res = true;
- done:
- g_free(in_str);
- if(jmain)
- json_object_put(jmain);
- return res;
- }
- static json_object *get_jmodel_obj(struct mesh_node *node, uint8_t ele_idx,
- uint32_t model_id, json_object **jmain)
- {
- char *in_str;
- json_object *jnode;
- json_object *jconfig;
- json_object *jelements, *jelement;
- json_object *jmodels, *jmodel = NULL;
- uint16_t primary = node_get_primary(node);
- const char *filename;
- bool local = (node == node_get_local_node());
- if (local)
- filename = local_filename;
- else
- filename = prov_filename;
- in_str = prov_file_read(filename);
- if (!in_str)
- return NULL;
- *jmain = json_tokener_parse(in_str);
- if (!(*jmain))
- goto done;
- if (local)
- json_object_object_get_ex(*jmain, "node", &jnode);
- else
- jnode = find_node_by_primary(*jmain, primary);
- if (!jnode)
- goto done;
- /* Configuration is mandatory for nodes in provisioning database */
- json_object_object_get_ex(jnode, "configuration", &jconfig);
- if (!jconfig)
- goto done;
- json_object_object_get_ex(jconfig, "elements", &jelements);
- if (!jelements) {
- goto done;
- }
- jelement = json_object_array_get_idx(jelements, ele_idx);
- if (!jelement) {
- goto done;
- }
- json_object_object_get_ex(jelement, "models", &jmodels);
- if (!jmodels) {
- jmodels = json_object_new_array();
- json_object_object_add(jelement, "models", jmodels);
- } else {
- jmodel = find_configured_model(node, ele_idx, jmodels,
- model_id);
- }
- if (!jmodel) {
- jmodel = json_object_new_object();
- if ((model_id & 0xffff0000) == 0xffff0000)
- put_uint16(jmodel, "modelId", model_id & 0xffff);
- else
- put_uint32(jmodel, "modelId", model_id);
- json_object_array_add(jmodels, jmodel);
- }
- done:
- g_free(in_str);
- if(!jmodel && *jmain)
- json_object_put(*jmain);
- return jmodel;
- }
- bool prov_db_add_binding(struct mesh_node *node, uint8_t ele_idx,
- uint32_t model_id, uint16_t app_idx)
- {
- bool local = (node == node_get_local_node());
- json_object *jbindings = NULL;
- json_object *jmodel;
- json_object *jvalue;
- json_object *jmain;
- jmodel = get_jmodel_obj(node, ele_idx, model_id, &jmain);
- if (!jmodel)
- return false;
- json_object_object_get_ex(jmodel, "bind", &jbindings);
- if (!jbindings) {
- jbindings = json_object_new_array();
- json_object_object_add(jmodel, "bind", jbindings);
- }
- jvalue = json_object_new_int(app_idx);
- json_object_array_add(jbindings, jvalue);
- prov_file_write(jmain, local);
- json_object_put(jmain);
- return true;
- }
- bool prov_db_add_subscription(struct mesh_node *node, uint8_t ele_idx,
- uint32_t model_id, uint16_t addr)
- {
- bool local = (node == node_get_local_node());
- json_object *jsubscriptions = NULL;
- json_object *jmodel;
- json_object *jmain;
- jmodel = get_jmodel_obj(node, ele_idx, model_id, &jmain);
- if (!jmodel)
- return false;
- json_object_object_get_ex(jmodel, "subscribe", &jsubscriptions);
- if (!jsubscriptions) {
- jsubscriptions = json_object_new_array();
- json_object_object_add(jmodel, "subscribe", jsubscriptions);
- }
- put_uint16_array_entry(jsubscriptions, addr);
- prov_file_write(jmain, local);
- json_object_put(jmain);
- return true;
- }
- bool prov_db_node_set_model_pub(struct mesh_node *node, uint8_t ele_idx,
- uint32_t model_id,
- struct mesh_publication *pub)
- {
- json_object *jmain;
- json_object *jmodel;
- json_object *jpub;
- json_object *jvalue;
- bool local = (node == node_get_local_node());
- jmodel = get_jmodel_obj(node, ele_idx, model_id, &jmain);
- if (!jmodel)
- return false;
- json_object_object_del(jmodel, "publish");
- if (!pub)
- goto done;
- jpub = json_object_new_object();
- /* Save only required fields */
- put_uint16(jpub, "address", pub->u.addr16);
- put_uint16(jpub, "index", pub->app_idx);
- jvalue = json_object_new_int(pub->ttl);
- json_object_object_add(jpub, "ttl", jvalue);
- json_object_object_add(jmodel, "publish", jpub);
- done:
- prov_file_write(jmain, local);
- json_object_put(jmain);
- return true;
- }
- bool prov_db_add_new_node(struct mesh_node *node)
- {
- char *in_str;
- json_object *jmain;
- json_object *jarray;
- json_object *jnode;
- json_object *jconfig;
- json_object *jelements;
- uint8_t num_ele;
- uint16_t primary;
- int i;
- bool first_node;
- bool res = false;
- in_str = prov_file_read(prov_filename);
- if (!in_str)
- return false;
- jmain = json_tokener_parse(in_str);
- if (!jmain)
- goto done;
- json_object_object_get_ex(jmain, "nodes", &jarray);
- if (!jarray) {
- jarray = json_object_new_array();
- first_node = true;
- } else
- first_node = false;
- jnode = json_object_new_object();
- /* Device key */
- add_key(jnode, "deviceKey", node_get_device_key(node));
- /* Net key */
- jconfig = json_object_new_object();
- add_node_idxs(jconfig, "netKeys", node_get_net_keys(node));
- num_ele = node_get_num_elements(node);
- if (num_ele == 0)
- goto done;
- jelements = json_object_new_array();
- primary = node_get_primary(node);
- if (IS_UNASSIGNED(primary))
- goto done;
- for (i = 0; i < num_ele; ++i) {
- json_object *jelement;
- json_object *jint;
- jelement = json_object_new_object();
- /* Element Index */
- jint = json_object_new_int(i);
- json_object_object_add(jelement, "elementIndex", jint);
- /* Unicast */
- put_uint16(jelement, "unicastAddress", primary + i);
- json_object_array_add(jelements, jelement);
- }
- json_object_object_add(jconfig, "elements", jelements);
- json_object_object_add(jnode, "configuration", jconfig);
- json_object_array_add(jarray, jnode);
- if (first_node)
- json_object_object_add(jmain, "nodes", jarray);
- prov_file_write(jmain, false);
- res = true;
- done:
- g_free(in_str);
- if (jmain)
- json_object_put(jmain);
- return res;
- }
- static bool parse_node_composition(struct mesh_node *node, json_object *jcomp)
- {
- json_object *jvalue;
- json_object *jelements;
- json_object *jfeatures;
- json_bool enable;
- char *str;
- struct mesh_node_composition comp;
- json_object_object_get_ex(jcomp, "cid", &jvalue);
- if (!jvalue)
- return false;
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &comp.cid) != 1)
- return false;
- json_object_object_get_ex(jcomp, "pid", &jvalue);
- if (!jvalue)
- return false;
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &comp.pid) != 1)
- return false;
- json_object_object_get_ex(jcomp, "vid", &jvalue);
- if (!jvalue)
- return false;
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &comp.vid) != 1)
- return false;
- json_object_object_get_ex(jcomp, "crpl", &jvalue);
- if (!jvalue)
- return false;
- str = (char *)json_object_get_string(jvalue);
- if (sscanf(str, "%04hx", &comp.crpl) != 1)
- return false;
- /* Extract features */
- json_object_object_get_ex(jcomp, "features", &jfeatures);
- if (!jfeatures)
- return false;
- json_object_object_get_ex(jfeatures, "relay", &jvalue);
- enable = json_object_get_boolean(jvalue);
- comp.relay = (enable) ? true : false;
- json_object_object_get_ex(jfeatures, "proxy", &jvalue);
- enable = json_object_get_boolean(jvalue);
- comp.proxy = (enable) ? true : false;
- json_object_object_get_ex(jfeatures, "friend", &jvalue);
- enable = json_object_get_boolean(jvalue);
- comp.friend = (enable) ? true : false;
- json_object_object_get_ex(jfeatures, "lowPower", &jvalue);
- enable = json_object_get_boolean(jvalue);
- comp.lpn = (enable) ? true : false;
- if (!node_set_composition(node, &comp))
- return false;
- json_object_object_get_ex(jcomp, "elements", &jelements);
- if (!jelements)
- return false;
- return parse_composition_elements(node, jelements);
- }
- static bool parse_node(json_object *jnode, bool local)
- {
- json_object *jconfig;
- json_object *jelements;
- json_object *jidxs;
- json_object *jvalue;
- json_object *jint;
- uint8_t key[16];
- char *value_str;
- uint32_t idx;
- struct mesh_node *node;
- /* Device key */
- if (!json_object_object_get_ex(jnode, "deviceKey", &jvalue) ||
- !jvalue) {
- if (!mesh_get_random_bytes(key, 16))
- return false;
- add_key(jnode, "deviceKey", key);
- } else {
- value_str = (char *)json_object_get_string(jvalue);
- if (!str2hex(value_str, strlen(value_str), key, 16))
- return false;;
- }
- node = node_new();
- if (!node)
- return false;
- node_set_device_key(node, key);
- json_object_object_get_ex(jnode, "IVindex", &jint);
- if (jint)
- idx = json_object_get_int(jint);
- else
- idx = 0;
- node_set_iv_index(node, idx);
- if (local) {
- bool update = false;
- json_object_object_get_ex(jnode, "IVupdate", &jint);
- if (jint)
- update = json_object_get_int(jint) ? true : false;
- net_set_iv_index(idx, update);
- }
- if (json_object_object_get_ex(jnode, "sequenceNumber", &jint) &&
- jint) {
- int seq = json_object_get_int(jint);
- node_set_sequence_number(node, seq);
- }
- /* Composition is mandatory for local node */
- json_object_object_get_ex(jnode, "composition", &jconfig);
- if ((jconfig && !parse_node_composition(node, jconfig)) ||
- (!jconfig && local)) {
- node_free(node);
- return false;
- }
- /* Configuration is mandatory for nodes in provisioning database */
- json_object_object_get_ex(jnode, "configuration", &jconfig);
- if (!jconfig) {
- if (local) {
- /* This is an unprovisioned local device */
- goto done;
- } else {
- node_free(node);
- return false;
- }
- }
- json_object_object_get_ex(jconfig, "elements", &jelements);
- if (!jelements) {
- node_free(node);
- return false;
- }
- if (!parse_configuration_elements(node, jelements, local)) {
- node_free(node);
- return false;;
- }
- json_object_object_get_ex(jconfig, "netKeys", &jidxs);
- if (!jidxs || (parse_node_keys(node, jidxs, false) == 0)) {
- node_free(node);
- return false;
- }
- json_object_object_get_ex(jconfig, "appKeys", &jidxs);
- if (jidxs)
- parse_node_keys(node, jidxs, true);
- json_object_object_get_ex(jconfig, "defaultTTL", &jvalue);
- if (jvalue) {
- int ttl = json_object_get_int(jvalue);
- node_set_default_ttl(node, ttl &TTL_MASK);
- }
- done:
- if (local && !node_set_local_node(node)) {
- node_free(node);
- return false;
- }
- return true;
- }
- bool prov_db_show(const char *filename)
- {
- char *str;
- str = prov_file_read(filename);
- if (!str)
- return false;
- bt_shell_printf("%s\n", str);
- g_free(str);
- return true;
- }
- static bool read_json_db(const char *filename, bool provisioner, bool local)
- {
- char *str;
- json_object *jmain;
- json_object *jarray;
- json_object *jprov;
- json_object *jvalue;
- json_object *jtemp;
- uint8_t key[16];
- int value_int;
- char *value_str;
- int len;
- int i;
- uint32_t index;
- bool refresh = false;
- bool res = false;
- str = prov_file_read(filename);
- if (!str) return false;
- jmain = json_tokener_parse(str);
- if (!jmain)
- goto done;
- if (local) {
- json_object *jnode;
- bool result;
- json_object_object_get_ex(jmain, "node", &jnode);
- if (!jnode) {
- bt_shell_printf("Cannot find \"node\" object");
- goto done;
- } else
- result = parse_node(jnode, true);
- /*
- * If local node is provisioner, the rest of mesh settings
- * are read from provisioning database.
- */
- if (provisioner) {
- res = result;
- goto done;
- }
- }
- /* IV index */
- json_object_object_get_ex(jmain, "IVindex", &jvalue);
- if (!jvalue)
- goto done;
- index = json_object_get_int(jvalue);
- json_object_object_get_ex(jmain, "IVupdate", &jvalue);
- if (!jvalue)
- goto done;
- value_int = json_object_get_int(jvalue);
- net_set_iv_index(index, value_int);
- /* Network key(s) */
- json_object_object_get_ex(jmain, "netKeys", &jarray);
- if (!jarray)
- goto done;
- len = json_object_array_length(jarray);
- bt_shell_printf("# netkeys = %d\n", len);
- for (i = 0; i < len; ++i) {
- uint32_t idx;
- jtemp = json_object_array_get_idx(jarray, i);
- json_object_object_get_ex(jtemp, "index", &jvalue);
- if (!jvalue)
- goto done;
- idx = json_object_get_int(jvalue);
- json_object_object_get_ex(jtemp, "key", &jvalue);
- if (!jvalue) {
- if (!mesh_get_random_bytes(key, 16))
- goto done;
- add_key(jtemp, "key", key);
- refresh = true;
- } else {
- value_str = (char *)json_object_get_string(jvalue);
- if (!str2hex(value_str, strlen(value_str), key, 16)) {
- goto done;
- }
- }
- if (!keys_net_key_add(idx, key, false))
- goto done;
- json_object_object_get_ex(jtemp, "keyRefresh", &jvalue);
- if (!jvalue)
- goto done;
- keys_set_kr_phase(idx, (uint8_t) json_object_get_int(jvalue));
- }
- /* App keys */
- json_object_object_get_ex(jmain, "appKeys", &jarray);
- if (jarray) {
- len = json_object_array_length(jarray);
- bt_shell_printf("# appkeys = %d\n", len);
- for (i = 0; i < len; ++i) {
- int app_idx;
- int net_idx;
- jtemp = json_object_array_get_idx(jarray, i);
- json_object_object_get_ex(jtemp, "index",
- &jvalue);
- if (!jvalue)
- goto done;
- app_idx = json_object_get_int(jvalue);
- if (!CHECK_KEY_IDX_RANGE(app_idx))
- goto done;
- json_object_object_get_ex(jtemp, "key", &jvalue);
- if (!jvalue) {
- if (!mesh_get_random_bytes(key, 16))
- goto done;
- add_key(jtemp, "key", key);
- refresh = true;
- } else {
- value_str =
- (char *)json_object_get_string(jvalue);
- str2hex(value_str, strlen(value_str), key, 16);
- }
- json_object_object_get_ex(jtemp, "boundNetKey",
- &jvalue);
- if (!jvalue)
- goto done;
- net_idx = json_object_get_int(jvalue);
- if (!CHECK_KEY_IDX_RANGE(net_idx))
- goto done;
- keys_app_key_add(net_idx, app_idx, key, false);
- }
- }
- /* Provisioner info */
- json_object_object_get_ex(jmain, "provisioners", &jarray);
- if (!jarray)
- goto done;
- len = json_object_array_length(jarray);
- bt_shell_printf("# provisioners = %d\n", len);
- for (i = 0; i < len; ++i) {
- jprov = json_object_array_get_idx(jarray, i);
- /* Allocated unicast range */
- json_object_object_get_ex(jprov, "allocatedUnicastRange",
- &jtemp);
- if (!jtemp) {
- goto done;
- }
- if (!parse_unicast_range(jtemp)) {
- bt_shell_printf("Doneed to parse unicast range\n");
- goto done;
- }
- }
- json_object_object_get_ex(jmain, "nodes", &jarray);
- if (!jarray) {
- res = true;
- goto done;
- }
- len = json_object_array_length(jarray);
- bt_shell_printf("# provisioned nodes = %d\n", len);
- for (i = 0; i < len; ++i) {
- json_object *jnode;
- jnode = json_object_array_get_idx(jarray, i);
- if (!jnode || !parse_node(jnode, false))
- goto done;
- }
- res = true;
- done:
- g_free(str);
- if (res && refresh)
- prov_file_write(jmain, false);
- if (jmain)
- json_object_put(jmain);
- return res;
- }
- bool prov_db_read(const char *filename)
- {
- prov_filename = filename;
- return read_json_db(filename, true, false);
- }
- bool prov_db_read_local_node(const char *filename, bool provisioner)
- {
- local_filename = filename;
- return read_json_db(filename, provisioner, true);
- }
|