mesh-cfgclient.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2019 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 <assert.h>
  15. #include <ctype.h>
  16. #include <dbus/dbus.h>
  17. #include <errno.h>
  18. #include <libgen.h>
  19. #include <stdio.h>
  20. #include <time.h>
  21. #include <sys/stat.h>
  22. #include <ell/ell.h>
  23. #include "src/shared/shell.h"
  24. #include "src/shared/util.h"
  25. #include "mesh/mesh.h"
  26. #include "mesh/mesh-defs.h"
  27. #include "tools/mesh/agent.h"
  28. #include "tools/mesh/cfgcli.h"
  29. #include "tools/mesh/keys.h"
  30. #include "tools/mesh/mesh-db.h"
  31. #include "tools/mesh/model.h"
  32. #include "tools/mesh/remote.h"
  33. #define PROMPT_ON COLOR_BLUE "[mesh-cfgclient]" COLOR_OFF "# "
  34. #define PROMPT_OFF "Waiting to connect to bluetooth-meshd..."
  35. #define CFG_SRV_MODEL 0x0000
  36. #define CFG_CLI_MODEL 0x0001
  37. #define UNPROV_SCAN_MAX_SECS 300
  38. #define DEFAULT_START_ADDRESS 0x00aa
  39. #define DEFAULT_MAX_ADDRESS (VIRTUAL_ADDRESS_LOW - 1)
  40. #define DEFAULT_NET_INDEX 0x0000
  41. #define MAX_CRPL_SIZE 0x7fff
  42. #define DEFAULT_CFG_FILE "config_db.json"
  43. #define DEFAULT_EXPORT_FILE "export_db.json"
  44. struct meshcfg_el {
  45. const char *path;
  46. uint8_t index;
  47. uint16_t mods[2];
  48. };
  49. struct meshcfg_app {
  50. const char *path;
  51. const char *agent_path;
  52. struct meshcfg_el ele;
  53. uint16_t cid;
  54. uint16_t pid;
  55. uint16_t vid;
  56. uint16_t crpl;
  57. uint8_t uuid[16];
  58. };
  59. struct meshcfg_node {
  60. const char *path;
  61. struct l_dbus_proxy *proxy;
  62. struct l_dbus_proxy *mgmt_proxy;
  63. union {
  64. uint64_t u64;
  65. uint8_t u8[8];
  66. } token;
  67. };
  68. struct unprov_device {
  69. time_t last_seen;
  70. int16_t rssi;
  71. uint8_t uuid[16];
  72. };
  73. struct generic_request {
  74. uint32_t arg1;
  75. uint32_t arg2;
  76. uint32_t arg3;
  77. uint8_t *data1;
  78. uint8_t *data2;
  79. const char *str;
  80. };
  81. static struct l_dbus *dbus;
  82. static struct l_queue *node_proxies;
  83. static struct l_dbus_proxy *net_proxy;
  84. static struct meshcfg_node *local;
  85. static struct model_info *cfgcli;
  86. static struct l_queue *devices;
  87. static bool prov_in_progress;
  88. static const char * const caps[] = {"static-oob",
  89. "push",
  90. "twist",
  91. "blink",
  92. "beep",
  93. "vibrate",
  94. "public-oob",
  95. "out-alpha",
  96. "in-alpha",
  97. "out-numeric",
  98. "in-numeric"};
  99. static bool have_config;
  100. static struct meshcfg_app app = {
  101. .path = "/mesh/cfgclient",
  102. .agent_path = "/mesh/cfgclient/agent",
  103. .cid = 0x05f1,
  104. .pid = 0x0002,
  105. .vid = 0x0001,
  106. .crpl = MAX_CRPL_SIZE,
  107. .ele = {
  108. .path = "/mesh/cfgclient/ele0",
  109. .index = 0,
  110. .mods = {CFG_SRV_MODEL, CFG_CLI_MODEL}
  111. }
  112. };
  113. static const struct option options[] = {
  114. { "config", required_argument, 0, 'c' },
  115. { "address-start", required_argument, 0, 'a' },
  116. { "address-range", required_argument, 0, 'r' },
  117. { "net-index", required_argument, 0, 'n' },
  118. { 0, 0, 0, 0 }
  119. };
  120. static const char *address_opt;
  121. static const char *range_opt;
  122. static const char *net_idx_opt;
  123. static const char *config_opt;
  124. static uint32_t iv_index;
  125. static uint16_t low_addr;
  126. static uint16_t high_addr;
  127. static uint16_t prov_net_idx;
  128. static const char *cfg_fname;
  129. static const char **optargs[] = {
  130. &config_opt,
  131. &address_opt,
  132. &range_opt,
  133. &net_idx_opt,
  134. };
  135. static const char *help[] = {
  136. "Configuration file",
  137. "Starting unicast address for remote nodes",
  138. "Net index for provisioning subnet"
  139. };
  140. static const struct bt_shell_opt opt = {
  141. .options = options,
  142. .optno = sizeof(options) / sizeof(struct option),
  143. .optstr = "c:a:n:",
  144. .optarg = optargs,
  145. .help = help,
  146. };
  147. static const char *dbus_err_args = "org.freedesktop.DBus.Error.InvalidArgs";
  148. static const char *dbus_err_fail = "org.freedesktop.DBus.Error.Failed";
  149. static const char *dbus_err_support = "org.freedesktop.DBus.Error.NotSupported";
  150. static bool parse_argument_on_off(int argc, char *argv[], bool *value)
  151. {
  152. if (!strcmp(argv[1], "on") || !strcmp(argv[1], "yes")) {
  153. *value = TRUE;
  154. return TRUE;
  155. }
  156. if (!strcmp(argv[1], "off") || !strcmp(argv[1], "no")) {
  157. *value = FALSE;
  158. return TRUE;
  159. }
  160. bt_shell_printf("Invalid argument %s\n", argv[1]);
  161. return FALSE;
  162. }
  163. static bool match_device_uuid(const void *a, const void *b)
  164. {
  165. const struct unprov_device *dev = a;
  166. const uint8_t *uuid = b;
  167. return (memcmp(dev->uuid, uuid, 16) == 0);
  168. }
  169. static void print_device(void *a, void *b)
  170. {
  171. const struct unprov_device *dev = a;
  172. struct tm *tm = localtime(&dev->last_seen);
  173. char buf[80];
  174. char *str;
  175. assert(strftime(buf, sizeof(buf), "%c", tm));
  176. str = l_util_hexstring_upper(dev->uuid, sizeof(dev->uuid));
  177. bt_shell_printf("UUID: %s, RSSI %d, Seen: %s\n",
  178. str, dev->rssi, buf);
  179. l_free(str);
  180. }
  181. struct send_data {
  182. const char *ele_path;
  183. bool rmt;
  184. bool is_dev_key;
  185. uint16_t dst;
  186. uint16_t idx;
  187. uint8_t *data;
  188. uint16_t len;
  189. };
  190. struct key_data {
  191. const char *ele_path;
  192. uint16_t dst;
  193. uint16_t idx;
  194. uint16_t net_idx;
  195. bool update;
  196. };
  197. static void append_dict_entry_basic(struct l_dbus_message_builder *builder,
  198. const char *key, const char *signature,
  199. const void *data)
  200. {
  201. if (!builder)
  202. return;
  203. l_dbus_message_builder_enter_dict(builder, "sv");
  204. l_dbus_message_builder_append_basic(builder, 's', key);
  205. l_dbus_message_builder_enter_variant(builder, signature);
  206. l_dbus_message_builder_append_basic(builder, signature[0], data);
  207. l_dbus_message_builder_leave_variant(builder);
  208. l_dbus_message_builder_leave_dict(builder);
  209. }
  210. static void append_byte_array(struct l_dbus_message_builder *builder,
  211. unsigned char *data, unsigned int len)
  212. {
  213. unsigned int i;
  214. l_dbus_message_builder_enter_array(builder, "y");
  215. for (i = 0; i < len; i++)
  216. l_dbus_message_builder_append_basic(builder, 'y', &(data[i]));
  217. l_dbus_message_builder_leave_array(builder);
  218. }
  219. static void send_msg_setup(struct l_dbus_message *msg, void *user_data)
  220. {
  221. struct send_data *req = user_data;
  222. struct l_dbus_message_builder *builder;
  223. builder = l_dbus_message_builder_new(msg);
  224. l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
  225. l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
  226. if (req->is_dev_key)
  227. l_dbus_message_builder_append_basic(builder, 'b', &req->rmt);
  228. l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
  229. /* Options */
  230. l_dbus_message_builder_enter_array(builder, "{sv}");
  231. l_dbus_message_builder_enter_dict(builder, "sv");
  232. l_dbus_message_builder_leave_dict(builder);
  233. l_dbus_message_builder_leave_array(builder);
  234. /* Data */
  235. append_byte_array(builder, req->data, req->len);
  236. l_dbus_message_builder_finalize(builder);
  237. l_dbus_message_builder_destroy(builder);
  238. }
  239. static bool send_msg(void *user_data, uint16_t dst, uint16_t idx,
  240. uint8_t *data, uint16_t len)
  241. {
  242. struct send_data *req;
  243. uint16_t net_idx_tx = idx;
  244. bool is_dev_key;
  245. const char *method_name;
  246. is_dev_key = (idx == APP_IDX_DEV_REMOTE || idx == APP_IDX_DEV_LOCAL);
  247. method_name = is_dev_key ? "DevKeySend" : "Send";
  248. if (is_dev_key) {
  249. net_idx_tx = remote_get_subnet_idx(dst);
  250. if (net_idx_tx == NET_IDX_INVALID)
  251. return false;
  252. }
  253. req = l_new(struct send_data, 1);
  254. req->ele_path = user_data;
  255. req->dst = dst;
  256. req->idx = net_idx_tx;
  257. req->data = data;
  258. req->len = len;
  259. req->rmt = (idx == APP_IDX_DEV_REMOTE);
  260. req->is_dev_key = is_dev_key;
  261. return l_dbus_proxy_method_call(local->proxy, method_name,
  262. send_msg_setup, NULL, req, l_free) != 0;
  263. }
  264. static void send_key_setup(struct l_dbus_message *msg, void *user_data)
  265. {
  266. struct key_data *req = user_data;
  267. struct l_dbus_message_builder *builder;
  268. builder = l_dbus_message_builder_new(msg);
  269. l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
  270. l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
  271. l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
  272. l_dbus_message_builder_append_basic(builder, 'q', &req->net_idx);
  273. l_dbus_message_builder_append_basic(builder, 'b', &req->update);
  274. l_dbus_message_builder_finalize(builder);
  275. l_dbus_message_builder_destroy(builder);
  276. }
  277. static bool send_key(void *user_data, uint16_t dst, uint16_t key_idx,
  278. bool is_appkey, bool update)
  279. {
  280. struct key_data *req;
  281. uint16_t net_idx;
  282. const char *method_name = (!is_appkey) ? "AddNetKey" : "AddAppKey";
  283. net_idx = remote_get_subnet_idx(dst);
  284. if (net_idx == NET_IDX_INVALID) {
  285. bt_shell_printf("Node %4.4x not found\n", dst);
  286. return false;
  287. }
  288. if (!is_appkey && !keys_subnet_exists(key_idx)) {
  289. bt_shell_printf("Local NetKey %u (0x%3.3x) not found\n",
  290. key_idx, key_idx);
  291. return false;
  292. }
  293. if (is_appkey && (keys_get_bound_key(key_idx) == NET_IDX_INVALID)) {
  294. bt_shell_printf("Local AppKey %u (0x%3.3x) not found\n",
  295. key_idx, key_idx);
  296. return false;
  297. }
  298. req = l_new(struct key_data, 1);
  299. req->ele_path = user_data;
  300. req->dst = dst;
  301. req->idx = key_idx;
  302. req->net_idx = net_idx;
  303. req->update = update;
  304. return l_dbus_proxy_method_call(local->proxy, method_name,
  305. send_key_setup, NULL, req, l_free) != 0;
  306. }
  307. static void delete_node_setup(struct l_dbus_message *msg, void *user_data)
  308. {
  309. struct generic_request *req = user_data;
  310. uint16_t primary;
  311. uint8_t ele_cnt;
  312. primary = (uint16_t) req->arg1;
  313. ele_cnt = (uint8_t) req->arg2;
  314. l_dbus_message_set_arguments(msg, "qy", primary, ele_cnt);
  315. }
  316. static void delete_node(uint16_t primary, uint8_t ele_cnt)
  317. {
  318. struct generic_request *req;
  319. if (!local || !local->proxy || !local->mgmt_proxy) {
  320. bt_shell_printf("Node is not attached\n");
  321. return;
  322. }
  323. req = l_new(struct generic_request, 1);
  324. req->arg1 = primary;
  325. req->arg2 = ele_cnt;
  326. l_dbus_proxy_method_call(local->mgmt_proxy, "DeleteRemoteNode",
  327. delete_node_setup, NULL, req, l_free);
  328. }
  329. static void client_init(void)
  330. {
  331. cfgcli = cfgcli_init(send_key, delete_node, (void *) app.ele.path);
  332. cfgcli->ops.set_send_func(send_msg, (void *) app.ele.path);
  333. }
  334. static bool caps_getter(struct l_dbus *dbus,
  335. struct l_dbus_message *message,
  336. struct l_dbus_message_builder *builder,
  337. void *user_data)
  338. {
  339. uint32_t i;
  340. if (!l_dbus_message_builder_enter_array(builder, "s"))
  341. return false;
  342. for (i = 0; i < L_ARRAY_SIZE(caps); i++)
  343. l_dbus_message_builder_append_basic(builder, 's', caps[i]);
  344. l_dbus_message_builder_leave_array(builder);
  345. return true;
  346. }
  347. static void agent_input_done(oob_type_t type, void *buf, uint16_t len,
  348. void *user_data)
  349. {
  350. struct l_dbus_message *msg = user_data;
  351. struct l_dbus_message *reply = NULL;
  352. struct l_dbus_message_builder *builder;
  353. uint32_t val_u32;
  354. uint8_t oob_data[64];
  355. switch (type) {
  356. case NONE:
  357. case OUTPUT:
  358. default:
  359. break;
  360. case ASCII:
  361. if (len > 8) {
  362. bt_shell_printf("Bad input length\n");
  363. break;
  364. }
  365. /* Fall Through */
  366. case HEXADECIMAL:
  367. if (len > sizeof(oob_data)) {
  368. bt_shell_printf("Bad input length\n");
  369. break;
  370. }
  371. memset(oob_data, 0, sizeof(oob_data));
  372. memcpy(oob_data, buf, len);
  373. reply = l_dbus_message_new_method_return(msg);
  374. builder = l_dbus_message_builder_new(reply);
  375. append_byte_array(builder, oob_data, len);
  376. l_dbus_message_builder_finalize(builder);
  377. l_dbus_message_builder_destroy(builder);
  378. break;
  379. case DECIMAL:
  380. if (len > 8) {
  381. bt_shell_printf("Bad input length\n");
  382. break;
  383. }
  384. val_u32 = l_get_be32(buf);
  385. reply = l_dbus_message_new_method_return(msg);
  386. l_dbus_message_set_arguments(reply, "u", val_u32);
  387. break;
  388. }
  389. if (!reply)
  390. reply = l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  391. l_dbus_send(dbus, reply);
  392. }
  393. struct requested_action {
  394. const char *action;
  395. const char *description;
  396. };
  397. static struct requested_action display_numeric_table[] = {
  398. { "push", "Push remote button %d times"},
  399. { "twist", "Twist remote nob %d times"},
  400. { "in-numeric", "Enter %d on remote device"},
  401. { "out-numeric", "Enter %d on remote device"}
  402. };
  403. static struct requested_action prompt_numeric_table[] = {
  404. { "blink", "Enter the number of times remote LED blinked"},
  405. { "beep", "Enter the number of times remote device beeped"},
  406. { "vibrate", "Enter the number of times remote device vibrated"},
  407. { "in-numeric", "Enter the number displayed on remote device"},
  408. { "out-numeric", "Enter the number displayed on remote device"}
  409. };
  410. static int get_action(char *str, bool prompt)
  411. {
  412. struct requested_action *action_table;
  413. size_t len;
  414. int i, sz;
  415. if (!str)
  416. return -1;
  417. if (prompt) {
  418. len = strlen(str);
  419. sz = L_ARRAY_SIZE(prompt_numeric_table);
  420. action_table = prompt_numeric_table;
  421. } else {
  422. len = strlen(str);
  423. sz = L_ARRAY_SIZE(display_numeric_table);
  424. action_table = display_numeric_table;
  425. }
  426. for (i = 0; i < sz; ++i)
  427. if (len == strlen(action_table[i].action) &&
  428. !strcmp(str, action_table[i].action))
  429. return i;
  430. return -1;
  431. }
  432. static struct l_dbus_message *disp_numeric_call(struct l_dbus *dbus,
  433. struct l_dbus_message *msg,
  434. void *user_data)
  435. {
  436. char *str;
  437. uint32_t n;
  438. int action_index;
  439. if (!l_dbus_message_get_arguments(msg, "su", &str, &n)) {
  440. l_error("Cannot parse \"DisplayNumeric\" arguments");
  441. return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  442. }
  443. action_index = get_action(str, false);
  444. if (action_index < 0)
  445. return l_dbus_message_new_error(msg, dbus_err_support, NULL);
  446. str = l_strdup_printf(display_numeric_table[action_index].description,
  447. n);
  448. bt_shell_printf(COLOR_YELLOW "%s\n" COLOR_OFF, str);
  449. l_free(str);
  450. return l_dbus_message_new_method_return(msg);
  451. }
  452. static struct l_dbus_message *disp_string_call(struct l_dbus *dbus,
  453. struct l_dbus_message *msg,
  454. void *user_data)
  455. {
  456. const char *prompt = "Enter AlphaNumeric code on remote device:";
  457. char *str;
  458. if (!l_dbus_message_get_arguments(msg, "s", &str)) {
  459. l_error("Cannot parse \"DisplayString\" arguments");
  460. return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  461. }
  462. bt_shell_printf(COLOR_YELLOW "%s %s\n" COLOR_OFF, prompt, str);
  463. return l_dbus_message_new_method_return(msg);
  464. }
  465. static struct l_dbus_message *prompt_numeric_call(struct l_dbus *dbus,
  466. struct l_dbus_message *msg,
  467. void *user_data)
  468. {
  469. char *str;
  470. int action_index;
  471. const char *desc;
  472. if (!l_dbus_message_get_arguments(msg, "s", &str)) {
  473. l_error("Cannot parse \"PromptNumeric\" arguments");
  474. return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  475. }
  476. action_index = get_action(str, true);
  477. if (action_index < 0)
  478. return l_dbus_message_new_error(msg, dbus_err_support, NULL);
  479. desc = prompt_numeric_table[action_index].description;
  480. l_dbus_message_ref(msg);
  481. agent_input_request(DECIMAL, 8, desc, agent_input_done, msg);
  482. return NULL;
  483. }
  484. static struct l_dbus_message *prompt_public_call(struct l_dbus *dbus,
  485. struct l_dbus_message *msg,
  486. void *user_data)
  487. {
  488. l_dbus_message_ref(msg);
  489. agent_input_request(HEXADECIMAL, 64, "Enter 512 bit Public Key",
  490. agent_input_done, msg);
  491. return NULL;
  492. }
  493. static struct l_dbus_message *prompt_static_call(struct l_dbus *dbus,
  494. struct l_dbus_message *msg,
  495. void *user_data)
  496. {
  497. char *str;
  498. if (!l_dbus_message_get_arguments(msg, "s", &str) || !str) {
  499. l_error("Cannot parse \"PromptStatic\" arguments");
  500. return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  501. }
  502. if (!strcmp(str, "in-alpha") || !strcmp(str, "out-alpha")) {
  503. l_dbus_message_ref(msg);
  504. agent_input_request(ASCII, 8, "Enter displayed Ascii code",
  505. agent_input_done, msg);
  506. } else if (!strcmp(str, "static-oob")) {
  507. l_dbus_message_ref(msg);
  508. agent_input_request(HEXADECIMAL, 16, "Enter Static Key",
  509. agent_input_done, msg);
  510. } else
  511. return l_dbus_message_new_error(msg, dbus_err_support, NULL);
  512. return NULL;
  513. }
  514. static void setup_agent_iface(struct l_dbus_interface *iface)
  515. {
  516. l_dbus_interface_property(iface, "Capabilities", 0, "as", caps_getter,
  517. NULL);
  518. /* TODO: Other properties */
  519. l_dbus_interface_method(iface, "DisplayString", 0, disp_string_call,
  520. "", "s", "value");
  521. l_dbus_interface_method(iface, "DisplayNumeric", 0, disp_numeric_call,
  522. "", "su", "type", "number");
  523. l_dbus_interface_method(iface, "PromptNumeric", 0, prompt_numeric_call,
  524. "u", "s", "number", "type");
  525. l_dbus_interface_method(iface, "PromptStatic", 0, prompt_static_call,
  526. "ay", "s", "data", "type");
  527. l_dbus_interface_method(iface, "PublicKey", 0, prompt_public_call,
  528. "ay", "", "data");
  529. }
  530. static bool register_agent(void)
  531. {
  532. if (!l_dbus_register_interface(dbus, MESH_PROVISION_AGENT_INTERFACE,
  533. setup_agent_iface, NULL, false)) {
  534. l_error("Unable to register agent interface");
  535. return false;
  536. }
  537. if (!l_dbus_register_object(dbus, app.agent_path, NULL, NULL,
  538. MESH_PROVISION_AGENT_INTERFACE, NULL, NULL)) {
  539. l_error("Failed to register object %s", app.agent_path);
  540. return false;
  541. }
  542. if (!l_dbus_object_add_interface(dbus, app.agent_path,
  543. L_DBUS_INTERFACE_PROPERTIES, NULL)) {
  544. l_error("Failed to add interface %s",
  545. L_DBUS_INTERFACE_PROPERTIES);
  546. return false;
  547. }
  548. return true;
  549. }
  550. static void try_set_node_proxy(void *a, void *b)
  551. {
  552. struct l_dbus_proxy *proxy = a;
  553. const char *interface = l_dbus_proxy_get_interface(proxy);
  554. const char *path = l_dbus_proxy_get_path(proxy);
  555. if (strcmp(local->path, path))
  556. return;
  557. if (!strcmp(interface, MESH_MANAGEMENT_INTERFACE))
  558. local->mgmt_proxy = proxy;
  559. else if (!strcmp(interface, MESH_NODE_INTERFACE))
  560. local->proxy = proxy;
  561. }
  562. static void attach_node_reply(struct l_dbus_proxy *proxy,
  563. struct l_dbus_message *msg, void *user_data)
  564. {
  565. struct meshcfg_node *node = user_data;
  566. struct l_dbus_message_iter iter_cfg;
  567. uint32_t ivi;
  568. if (l_dbus_message_is_error(msg)) {
  569. const char *name;
  570. l_dbus_message_get_error(msg, &name, NULL);
  571. l_error("Failed to attach node: %s", name);
  572. goto fail;
  573. }
  574. if (!l_dbus_message_get_arguments(msg, "oa(ya(qa{sv}))",
  575. &local->path, &iter_cfg))
  576. goto fail;
  577. bt_shell_printf("Attached with path %s\n", local->path);
  578. /* Populate node's proxies */
  579. l_queue_foreach(node_proxies, try_set_node_proxy, node);
  580. /* Remove from orphaned proxies list */
  581. if (local->proxy)
  582. l_queue_remove(node_proxies, local->proxy);
  583. if (local->mgmt_proxy)
  584. l_queue_remove(node_proxies, local->mgmt_proxy);
  585. /* Inititalize config client model */
  586. client_init();
  587. if (l_dbus_proxy_get_property(local->proxy, "IvIndex", "u", &ivi) &&
  588. ivi != iv_index) {
  589. iv_index = ivi;
  590. mesh_db_set_iv_index(ivi);
  591. remote_clear_rejected_addresses(ivi);
  592. }
  593. return;
  594. fail:
  595. l_free(node);
  596. node = NULL;
  597. }
  598. static void attach_node_setup(struct l_dbus_message *msg, void *user_data)
  599. {
  600. l_dbus_message_set_arguments(msg, "ot", app.path,
  601. l_get_be64(local->token.u8));
  602. }
  603. static void create_net_reply(struct l_dbus_proxy *proxy,
  604. struct l_dbus_message *msg, void *user_data)
  605. {
  606. if (l_dbus_message_is_error(msg)) {
  607. const char *name;
  608. l_dbus_message_get_error(msg, &name, NULL);
  609. l_error("Failed to create network: %s", name);
  610. return;
  611. }
  612. }
  613. static void create_net_setup(struct l_dbus_message *msg, void *user_data)
  614. {
  615. struct l_dbus_message_builder *builder;
  616. /* Generate random UUID */
  617. l_uuid_v4(app.uuid);
  618. builder = l_dbus_message_builder_new(msg);
  619. l_dbus_message_builder_append_basic(builder, 'o', app.path);
  620. append_byte_array(builder, app.uuid, 16);
  621. l_dbus_message_builder_finalize(builder);
  622. l_dbus_message_builder_destroy(builder);
  623. }
  624. static void cmd_create_network(int argc, char *argv[])
  625. {
  626. if (have_config) {
  627. l_error("Mesh network configuration exists (%s)", cfg_fname);
  628. return;
  629. }
  630. l_dbus_proxy_method_call(net_proxy, "CreateNetwork", create_net_setup,
  631. create_net_reply, NULL,
  632. NULL);
  633. }
  634. static void scan_reply(struct l_dbus_proxy *proxy, struct l_dbus_message *msg,
  635. void *user_data)
  636. {
  637. if (l_dbus_message_is_error(msg)) {
  638. const char *name;
  639. l_dbus_message_get_error(msg, &name, NULL);
  640. l_error("Failed to start unprovisioned scan: %s", name);
  641. return;
  642. }
  643. bt_shell_printf("Unprovisioned scan started\n");
  644. }
  645. static void scan_setup(struct l_dbus_message *msg, void *user_data)
  646. {
  647. uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
  648. struct l_dbus_message_builder *builder;
  649. builder = l_dbus_message_builder_new(msg);
  650. l_dbus_message_builder_enter_array(builder, "{sv}");
  651. append_dict_entry_basic(builder, "Seconds", "q", &secs);
  652. l_dbus_message_builder_leave_array(builder);
  653. l_dbus_message_builder_finalize(builder);
  654. l_dbus_message_builder_destroy(builder);
  655. }
  656. static void cmd_scan_unprov(int argc, char *argv[])
  657. {
  658. uint32_t secs = 0;
  659. bool enable;
  660. if (!local || !local->proxy || !local->mgmt_proxy) {
  661. bt_shell_printf("Node is not attached\n");
  662. return;
  663. }
  664. if (parse_argument_on_off(argc, argv, &enable) == FALSE) {
  665. bt_shell_printf("Failed to parse input\n");
  666. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  667. }
  668. if (argc == 3)
  669. sscanf(argv[2], "%u", &secs);
  670. if (secs > UNPROV_SCAN_MAX_SECS)
  671. secs = UNPROV_SCAN_MAX_SECS;
  672. if (enable)
  673. l_dbus_proxy_method_call(local->mgmt_proxy, "UnprovisionedScan",
  674. scan_setup, scan_reply,
  675. L_UINT_TO_PTR(secs), NULL);
  676. else
  677. l_dbus_proxy_method_call(local->mgmt_proxy,
  678. "UnprovisionedScanCancel",
  679. NULL, NULL, NULL, NULL);
  680. }
  681. static uint8_t *parse_key(struct l_dbus_message_iter *iter, uint16_t id,
  682. const char *name)
  683. {
  684. uint8_t *val;
  685. uint32_t len;
  686. if (!l_dbus_message_iter_get_fixed_array(iter, &val, &len)
  687. || len != 16) {
  688. bt_shell_printf("Failed to parse %s %4.4x\n", name, id);
  689. return NULL;
  690. }
  691. return val;
  692. }
  693. static bool parse_app_keys(struct l_dbus_message_iter *iter, uint16_t net_idx,
  694. void *user_data)
  695. {
  696. struct l_dbus_message_iter app_keys, app_key, opts;
  697. uint16_t app_idx;
  698. if (!l_dbus_message_iter_get_variant(iter, "a(qaya{sv})", &app_keys))
  699. return false;
  700. while (l_dbus_message_iter_next_entry(&app_keys, &app_idx, &app_key,
  701. &opts)) {
  702. struct l_dbus_message_iter var;
  703. uint8_t *val, *old_val = NULL;
  704. const char *key;
  705. val = parse_key(&app_key, app_idx, "AppKey");
  706. if (!val)
  707. return false;
  708. while (l_dbus_message_iter_next_entry(&opts, &key, &var)) {
  709. if (!strcmp(key, "OldKey")) {
  710. if (!l_dbus_message_iter_get_variant(&var, "ay",
  711. &app_key))
  712. return false;
  713. old_val = parse_key(&app_key, app_idx,
  714. "old NetKey");
  715. if (!old_val)
  716. return false;
  717. }
  718. }
  719. mesh_db_set_app_key(user_data, net_idx, app_idx, val, old_val);
  720. }
  721. return true;
  722. }
  723. static bool parse_net_keys(struct l_dbus_message_iter *iter, void *user_data)
  724. {
  725. struct l_dbus_message_iter net_keys, net_key, opts;
  726. uint16_t idx;
  727. if (!l_dbus_message_iter_get_variant(iter, "a(qaya{sv})", &net_keys))
  728. return false;
  729. while (l_dbus_message_iter_next_entry(&net_keys, &idx, &net_key,
  730. &opts)) {
  731. struct l_dbus_message_iter var;
  732. uint8_t *val, *old_val = NULL;
  733. uint8_t phase = KEY_REFRESH_PHASE_NONE;
  734. const char *key;
  735. val = parse_key(&net_key, idx, "NetKey");
  736. if (!val)
  737. return false;
  738. while (l_dbus_message_iter_next_entry(&opts, &key, &var)) {
  739. if (!strcmp(key, "AppKeys")) {
  740. if (!parse_app_keys(&var, idx, user_data))
  741. return false;
  742. } else if (!strcmp(key, "Phase")) {
  743. if (!l_dbus_message_iter_get_variant(&var, "y",
  744. &phase))
  745. return false;
  746. } else if (!strcmp(key, "OldKey")) {
  747. if (!l_dbus_message_iter_get_variant(&var, "ay",
  748. &net_key))
  749. return false;
  750. old_val = parse_key(&net_key, idx,
  751. "old NetKey");
  752. if (!old_val)
  753. return false;
  754. }
  755. }
  756. mesh_db_set_net_key(user_data, idx, val, old_val, phase);
  757. }
  758. return true;
  759. }
  760. static bool parse_dev_keys(struct l_dbus_message_iter *iter, void *user_data)
  761. {
  762. struct l_dbus_message_iter keys, dev_key;
  763. uint16_t unicast;
  764. if (!l_dbus_message_iter_get_variant(iter, "a(qay)", &keys))
  765. return false;
  766. while (l_dbus_message_iter_next_entry(&keys, &unicast, &dev_key)) {
  767. uint8_t *data;
  768. data = parse_key(&dev_key, unicast, "Device Key");
  769. if (!data)
  770. return false;
  771. mesh_db_set_device_key(user_data, unicast, data);
  772. }
  773. return true;
  774. }
  775. static void export_keys_reply(struct l_dbus_proxy *proxy,
  776. struct l_dbus_message *msg, void *user_data)
  777. {
  778. struct l_dbus_message_iter iter, var;
  779. char *cfg_dir = NULL, *fname = NULL;
  780. const char *key;
  781. bool is_error = true;
  782. if (l_dbus_message_is_error(msg)) {
  783. const char *name;
  784. l_dbus_message_get_error(msg, &name, NULL);
  785. bt_shell_printf("Failed to export keys: %s", name);
  786. goto done;
  787. }
  788. if (!l_dbus_message_get_arguments(msg, "a{sv}", &iter)) {
  789. bt_shell_printf("Malformed ExportKeys reply");
  790. goto done;
  791. }
  792. while (l_dbus_message_iter_next_entry(&iter, &key, &var)) {
  793. if (!strcmp(key, "NetKeys")) {
  794. if (!parse_net_keys(&var, user_data))
  795. goto done;
  796. } else if (!strcmp(key, "DevKeys")) {
  797. if (!parse_dev_keys(&var, user_data))
  798. goto done;
  799. }
  800. }
  801. is_error = false;
  802. cfg_dir = l_strdup(cfg_fname);
  803. cfg_dir = dirname(cfg_dir);
  804. fname = l_strdup_printf("%s/%s", cfg_dir, DEFAULT_EXPORT_FILE);
  805. done:
  806. if (mesh_db_finish_export(is_error, user_data, fname)) {
  807. if (!is_error)
  808. bt_shell_printf("Config DB is exported to %s\n", fname);
  809. }
  810. l_free(cfg_dir);
  811. l_free(fname);
  812. }
  813. static void cmd_export_db(int argc, char *argv[])
  814. {
  815. void *cfg_export;
  816. if (!local || !local->proxy || !local->mgmt_proxy) {
  817. bt_shell_printf("Node is not attached\n");
  818. return;
  819. }
  820. /* Generate a properly formatted DB from the local config */
  821. cfg_export = mesh_db_prepare_export();
  822. if (!cfg_export) {
  823. bt_shell_printf("Failed to prepare config db\n");
  824. return;
  825. }
  826. /* Export the keys from the daemon */
  827. l_dbus_proxy_method_call(local->mgmt_proxy, "ExportKeys", NULL,
  828. export_keys_reply, cfg_export, NULL);
  829. }
  830. static void cmd_list_unprov(int argc, char *argv[])
  831. {
  832. bt_shell_printf(COLOR_YELLOW "Unprovisioned devices:\n" COLOR_OFF);
  833. l_queue_foreach(devices, print_device, NULL);
  834. }
  835. static void cmd_list_nodes(int argc, char *argv[])
  836. {
  837. remote_print_all();
  838. }
  839. static void cmd_keys(int argc, char *argv[])
  840. {
  841. keys_print_keys();
  842. }
  843. static void free_generic_request(void *data)
  844. {
  845. struct generic_request *req = data;
  846. l_free(req->data1);
  847. l_free(req->data2);
  848. l_free(req);
  849. }
  850. static void import_node_reply(struct l_dbus_proxy *proxy,
  851. struct l_dbus_message *msg, void *user_data)
  852. {
  853. struct generic_request *req = user_data;
  854. uint16_t primary, net_idx;
  855. uint8_t ele_cnt;
  856. if (l_dbus_message_is_error(msg)) {
  857. const char *name;
  858. l_dbus_message_get_error(msg, &name, NULL);
  859. l_error("Failed to import remote node: %s", name);
  860. return;
  861. }
  862. net_idx = (uint16_t) req->arg1;
  863. primary = (uint16_t) req->arg2;
  864. ele_cnt = (uint8_t) req->arg3;
  865. remote_add_node(req->data1, primary, ele_cnt, net_idx);
  866. }
  867. static void import_node_setup(struct l_dbus_message *msg, void *user_data)
  868. {
  869. struct generic_request *req = user_data;
  870. uint16_t primary;
  871. uint8_t ele_cnt;
  872. struct l_dbus_message_builder *builder;
  873. primary = (uint16_t) req->arg2;
  874. ele_cnt = (uint8_t) req->arg3;
  875. builder = l_dbus_message_builder_new(msg);
  876. l_dbus_message_builder_append_basic(builder, 'q', &primary);
  877. l_dbus_message_builder_append_basic(builder, 'y', &ele_cnt);
  878. append_byte_array(builder, req->data2, 16);
  879. l_dbus_message_builder_finalize(builder);
  880. l_dbus_message_builder_destroy(builder);
  881. }
  882. static void cmd_import_node(int argc, char *argv[])
  883. {
  884. struct generic_request *req;
  885. size_t sz;
  886. if (!local || !local->proxy || !local->mgmt_proxy) {
  887. bt_shell_printf("Node is not attached\n");
  888. return;
  889. }
  890. if (argc < 6) {
  891. bt_shell_printf("UUID, element count and device key");
  892. bt_shell_printf("Unicast, element count and device key");
  893. bt_shell_printf("are required\n");
  894. return;
  895. }
  896. req = l_new(struct generic_request, 1);
  897. /* Device UUID */
  898. req->data1 = l_util_from_hexstring(argv[1], &sz);
  899. if (!req->data1 || sz != 16 || !l_uuid_is_valid(req->data1)) {
  900. l_error("Failed to generate UUID array from %s", argv[1]);
  901. goto fail;
  902. }
  903. /* NetKey Index*/
  904. if (sscanf(argv[2], "%04x", &req->arg1) != 1)
  905. goto fail;
  906. /* Unicast of the primary element */
  907. if (sscanf(argv[3], "%04x", &req->arg2) != 1)
  908. goto fail;
  909. /* Number of elements */
  910. if (sscanf(argv[4], "%u", &req->arg3) != 1)
  911. goto fail;
  912. /* DevKey */
  913. req->data2 = l_util_from_hexstring(argv[5], &sz);
  914. if (!req->data2 || sz != 16) {
  915. l_error("Failed to generate DevKey array from %s", argv[5]);
  916. goto fail;
  917. }
  918. l_dbus_proxy_method_call(local->mgmt_proxy, "ImportRemoteNode",
  919. import_node_setup, import_node_reply,
  920. req, free_generic_request);
  921. return;
  922. fail:
  923. free_generic_request(req);
  924. }
  925. static void subnet_set_phase_reply(struct l_dbus_proxy *proxy,
  926. struct l_dbus_message *msg, void *user_data)
  927. {
  928. struct generic_request *req = user_data;
  929. uint16_t net_idx;
  930. uint8_t phase;
  931. if (l_dbus_message_is_error(msg)) {
  932. const char *name;
  933. l_dbus_message_get_error(msg, &name, NULL);
  934. l_error("Failed to set subnet phase: %s", name);
  935. return;
  936. }
  937. net_idx = (uint16_t) req->arg1;
  938. phase = (uint8_t) req->arg2;
  939. if (phase == KEY_REFRESH_PHASE_THREE)
  940. phase = KEY_REFRESH_PHASE_NONE;
  941. keys_set_net_key_phase(net_idx, phase, true);
  942. }
  943. static void subnet_set_phase_setup(struct l_dbus_message *msg, void *user_data)
  944. {
  945. struct generic_request *req = user_data;
  946. uint16_t net_idx;
  947. uint8_t phase;
  948. net_idx = (uint16_t) req->arg1;
  949. phase = (uint8_t) req->arg2;
  950. l_dbus_message_set_arguments(msg, "qy", net_idx, phase);
  951. }
  952. static void cmd_subnet_set_phase(int argc, char *argv[])
  953. {
  954. struct generic_request *req;
  955. if (!local || !local->proxy || !local->mgmt_proxy) {
  956. bt_shell_printf("Node is not attached\n");
  957. return;
  958. }
  959. if (argc < 3) {
  960. bt_shell_printf("NetKey index and phase are required\n");
  961. return;
  962. }
  963. req = l_new(struct generic_request, 1);
  964. if (sscanf(argv[1], "%04x", &req->arg1) != 1)
  965. goto fail;
  966. if (sscanf(argv[2], "%d", &req->arg2) != 1)
  967. goto fail;
  968. l_dbus_proxy_method_call(local->mgmt_proxy, "SetKeyPhase",
  969. subnet_set_phase_setup,
  970. subnet_set_phase_reply, req, l_free);
  971. return;
  972. fail:
  973. l_free(req);
  974. }
  975. static void mgr_key_reply(struct l_dbus_proxy *proxy,
  976. struct l_dbus_message *msg, void *user_data)
  977. {
  978. struct generic_request *req = user_data;
  979. uint16_t idx = (uint16_t) req->arg1;
  980. const char *method = req->str;
  981. if (l_dbus_message_is_error(msg)) {
  982. const char *name;
  983. l_dbus_message_get_error(msg, &name, NULL);
  984. l_error("Method %s returned error: %s", method, name);
  985. bt_shell_printf("Method %s returned error: %s\n", method, name);
  986. return;
  987. }
  988. if (!strcmp("CreateSubnet", method)) {
  989. keys_add_net_key(idx);
  990. mesh_db_add_net_key(idx);
  991. } else if (!strcmp("DeleteSubnet", method)) {
  992. keys_del_net_key(idx);
  993. mesh_db_del_net_key(idx);
  994. } else if (!strcmp("UpdateSubnet", method)) {
  995. keys_set_net_key_phase(idx, KEY_REFRESH_PHASE_ONE, true);
  996. } else if (!strcmp("DeleteAppKey", method)) {
  997. keys_del_app_key(idx);
  998. mesh_db_del_app_key(idx);
  999. }
  1000. }
  1001. static void mgr_key_setup(struct l_dbus_message *msg, void *user_data)
  1002. {
  1003. struct generic_request *req = user_data;
  1004. uint16_t idx = (uint16_t) req->arg1;
  1005. l_dbus_message_set_arguments(msg, "q", idx);
  1006. }
  1007. static void mgr_key_cmd(int argc, char *argv[], const char *method_name)
  1008. {
  1009. struct generic_request *req;
  1010. if (!local || !local->proxy || !local->mgmt_proxy) {
  1011. bt_shell_printf("Node is not attached\n");
  1012. return;
  1013. }
  1014. if (argc < 2) {
  1015. bt_shell_printf("Missing required arguments\n");
  1016. return;
  1017. }
  1018. req = l_new(struct generic_request, 1);
  1019. if (sscanf(argv[1], "%04x", &req->arg1) != 1) {
  1020. l_free(req);
  1021. return;
  1022. }
  1023. req->str = method_name;
  1024. l_dbus_proxy_method_call(local->mgmt_proxy, method_name,
  1025. mgr_key_setup, mgr_key_reply,
  1026. req, l_free);
  1027. }
  1028. static void cmd_delete_appkey(int argc, char *argv[])
  1029. {
  1030. mgr_key_cmd(argc, argv, "DeleteAppKey");
  1031. }
  1032. static void cmd_update_appkey(int argc, char *argv[])
  1033. {
  1034. mgr_key_cmd(argc, argv, "UpdateAppKey");
  1035. }
  1036. static void cmd_delete_subnet(int argc, char *argv[])
  1037. {
  1038. mgr_key_cmd(argc, argv, "DeleteSubnet");
  1039. }
  1040. static void cmd_update_subnet(int argc, char *argv[])
  1041. {
  1042. mgr_key_cmd(argc, argv, "UpdateSubnet");
  1043. }
  1044. static void cmd_create_subnet(int argc, char *argv[])
  1045. {
  1046. mgr_key_cmd(argc, argv, "CreateSubnet");
  1047. }
  1048. static void add_key_reply(struct l_dbus_proxy *proxy,
  1049. struct l_dbus_message *msg, void *user_data)
  1050. {
  1051. struct generic_request *req = user_data;
  1052. uint16_t net_idx, app_idx;
  1053. const char *method = req->str;
  1054. if (l_dbus_message_is_error(msg)) {
  1055. const char *name;
  1056. l_dbus_message_get_error(msg, &name, NULL);
  1057. l_error("%s failed: %s", method, name);
  1058. return;
  1059. }
  1060. net_idx = (uint16_t) req->arg1;
  1061. if (!strcmp(method, "ImportSubnet")) {
  1062. keys_add_net_key(net_idx);
  1063. mesh_db_add_net_key(net_idx);
  1064. return;
  1065. }
  1066. app_idx = (uint16_t) req->arg2;
  1067. keys_add_app_key(net_idx, app_idx);
  1068. mesh_db_add_app_key(net_idx, app_idx);
  1069. }
  1070. static void import_appkey_setup(struct l_dbus_message *msg, void *user_data)
  1071. {
  1072. struct generic_request *req = user_data;
  1073. uint16_t net_idx, app_idx;
  1074. struct l_dbus_message_builder *builder;
  1075. net_idx = (uint16_t) req->arg1;
  1076. app_idx = (uint16_t) req->arg2;
  1077. builder = l_dbus_message_builder_new(msg);
  1078. l_dbus_message_builder_append_basic(builder, 'q', &net_idx);
  1079. l_dbus_message_builder_append_basic(builder, 'q', &app_idx);
  1080. append_byte_array(builder, req->data1, 16);
  1081. l_dbus_message_builder_finalize(builder);
  1082. l_dbus_message_builder_destroy(builder);
  1083. }
  1084. static void cmd_import_appkey(int argc, char *argv[])
  1085. {
  1086. struct generic_request *req;
  1087. size_t sz;
  1088. if (!local || !local->proxy || !local->mgmt_proxy) {
  1089. bt_shell_printf("Node is not attached\n");
  1090. return;
  1091. }
  1092. if (argc < 4) {
  1093. bt_shell_printf("Netkey and AppKey indices and");
  1094. bt_shell_printf("key value are required\n");
  1095. return;
  1096. }
  1097. req = l_new(struct generic_request, 1);
  1098. if (sscanf(argv[1], "%04x", &req->arg1) != 1)
  1099. goto fail;
  1100. if (sscanf(argv[2], "%04x", &req->arg2) != 1)
  1101. goto fail;
  1102. req->data1 = l_util_from_hexstring(argv[3], &sz);
  1103. if (!req->data1 || sz != 16) {
  1104. l_error("Failed to generate key array from %s", argv[3]);
  1105. goto fail;
  1106. }
  1107. req->str = "ImportAppKey";
  1108. l_dbus_proxy_method_call(local->mgmt_proxy, "ImportAppKey",
  1109. import_appkey_setup, add_key_reply,
  1110. req, free_generic_request);
  1111. return;
  1112. fail:
  1113. free_generic_request(req);
  1114. }
  1115. static void import_subnet_setup(struct l_dbus_message *msg, void *user_data)
  1116. {
  1117. struct generic_request *req = user_data;
  1118. uint16_t net_idx;
  1119. struct l_dbus_message_builder *builder;
  1120. net_idx = (uint16_t) req->arg1;
  1121. builder = l_dbus_message_builder_new(msg);
  1122. l_dbus_message_builder_append_basic(builder, 'q', &net_idx);
  1123. append_byte_array(builder, req->data1, 16);
  1124. l_dbus_message_builder_finalize(builder);
  1125. l_dbus_message_builder_destroy(builder);
  1126. }
  1127. static void cmd_import_subnet(int argc, char *argv[])
  1128. {
  1129. struct generic_request *req;
  1130. size_t sz;
  1131. if (!local || !local->proxy || !local->mgmt_proxy) {
  1132. bt_shell_printf("Node is not attached\n");
  1133. return;
  1134. }
  1135. if (argc < 3) {
  1136. bt_shell_printf("NetKey index and value are required\n");
  1137. return;
  1138. }
  1139. req = l_new(struct generic_request, 1);
  1140. if (sscanf(argv[1], "%04x", &req->arg1) != 1)
  1141. goto fail;
  1142. req->data1 = l_util_from_hexstring(argv[2], &sz);
  1143. if (!req->data1 || sz != 16) {
  1144. l_error("Failed to generate key array from %s", argv[2]);
  1145. goto fail;
  1146. }
  1147. req->str = "ImportSubnet";
  1148. l_dbus_proxy_method_call(local->mgmt_proxy, "ImportSubnet",
  1149. import_subnet_setup, add_key_reply,
  1150. req, free_generic_request);
  1151. return;
  1152. fail:
  1153. free_generic_request(req);
  1154. }
  1155. static void create_appkey_setup(struct l_dbus_message *msg, void *user_data)
  1156. {
  1157. struct generic_request *req = user_data;
  1158. uint16_t net_idx, app_idx;
  1159. net_idx = (uint16_t) req->arg1;
  1160. app_idx = (uint16_t) req->arg2;
  1161. l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
  1162. }
  1163. static void cmd_create_appkey(int argc, char *argv[])
  1164. {
  1165. struct generic_request *req;
  1166. if (!local || !local->proxy || !local->mgmt_proxy) {
  1167. bt_shell_printf("Node is not attached\n");
  1168. return;
  1169. }
  1170. if (argc < 3) {
  1171. bt_shell_printf("AppKey index is required\n");
  1172. return;
  1173. }
  1174. req = l_new(struct generic_request, 1);
  1175. if (sscanf(argv[1], "%04x", &req->arg1) != 1)
  1176. goto fail;
  1177. if (sscanf(argv[2], "%04x", &req->arg2) != 1)
  1178. goto fail;
  1179. req->str = "CreateAppKey";
  1180. l_dbus_proxy_method_call(local->mgmt_proxy, "CreateAppKey",
  1181. create_appkey_setup, add_key_reply,
  1182. req, l_free);
  1183. return;
  1184. fail:
  1185. l_free(req);
  1186. }
  1187. static void add_node_reply(struct l_dbus_proxy *proxy,
  1188. struct l_dbus_message *msg, void *user_data)
  1189. {
  1190. if (l_dbus_message_is_error(msg)) {
  1191. const char *name;
  1192. prov_in_progress = false;
  1193. l_dbus_message_get_error(msg, &name, NULL);
  1194. l_error("Failed to start provisioning: %s", name);
  1195. return;
  1196. }
  1197. bt_shell_printf("Provisioning started\n");
  1198. }
  1199. static void add_node_setup(struct l_dbus_message *msg, void *user_data)
  1200. {
  1201. char *str = user_data;
  1202. size_t sz;
  1203. unsigned char *uuid;
  1204. struct l_dbus_message_builder *builder;
  1205. uuid = l_util_from_hexstring(str, &sz);
  1206. if (!uuid || sz != 16 || !l_uuid_is_valid(uuid)) {
  1207. l_error("Failed to generate UUID array from %s", str);
  1208. return;
  1209. }
  1210. builder = l_dbus_message_builder_new(msg);
  1211. append_byte_array(builder, uuid, 16);
  1212. l_dbus_message_builder_enter_array(builder, "{sv}");
  1213. /* TODO: populate with options when defined */
  1214. l_dbus_message_builder_leave_array(builder);
  1215. l_dbus_message_builder_finalize(builder);
  1216. l_dbus_message_builder_destroy(builder);
  1217. l_free(uuid);
  1218. }
  1219. static void cmd_start_prov(int argc, char *argv[])
  1220. {
  1221. if (!local || !local->proxy || !local->mgmt_proxy) {
  1222. bt_shell_printf("Node is not attached\n");
  1223. return;
  1224. }
  1225. if (prov_in_progress) {
  1226. bt_shell_printf("Provisioning is already in progress\n");
  1227. return;
  1228. }
  1229. if (!argv[1] || (strlen(argv[1]) != 32)) {
  1230. bt_shell_printf(COLOR_RED "Requires UUID\n" COLOR_RED);
  1231. return;
  1232. }
  1233. if (l_dbus_proxy_method_call(local->mgmt_proxy, "AddNode",
  1234. add_node_setup, add_node_reply,
  1235. argv[1], NULL))
  1236. prov_in_progress = true;
  1237. }
  1238. static const struct bt_shell_menu main_menu = {
  1239. .name = "main",
  1240. .entries = {
  1241. { "create", "[unicast_range_low]", cmd_create_network,
  1242. "Create new mesh network with one initial node" },
  1243. { "discover-unprovisioned", "<on/off> [seconds]", cmd_scan_unprov,
  1244. "Look for devices to provision" },
  1245. { "appkey-create", "<net_idx> <app_idx>", cmd_create_appkey,
  1246. "Create a new local AppKey" },
  1247. { "appkey-import", "<net_idx> <app_idx> <key>", cmd_import_appkey,
  1248. "Import a new local AppKey" },
  1249. { "appkey-update", "<app_idx>", cmd_update_appkey,
  1250. "Update local AppKey" },
  1251. { "appkey-delete", "<app_idx>", cmd_delete_appkey,
  1252. "Delete local AppKey" },
  1253. { "subnet-create", "<net_idx>", cmd_create_subnet,
  1254. "Create a new local subnet (NetKey)" },
  1255. { "subnet-import", "<net_idx> <key>", cmd_import_subnet,
  1256. "Import a new local subnet (NetKey)" },
  1257. { "subnet-update", "<net_idx>", cmd_update_subnet,
  1258. "Update local subnet (NetKey)" },
  1259. { "subnet-delete", "<net_idx>", cmd_delete_subnet,
  1260. "Delete local subnet (NetKey)" },
  1261. { "subnet-set-phase", "<net_idx> <phase>", cmd_subnet_set_phase,
  1262. "Set subnet (NetKey) phase" },
  1263. { "list-unprovisioned", NULL, cmd_list_unprov,
  1264. "List unprovisioned devices" },
  1265. { "provision", "<uuid>", cmd_start_prov,
  1266. "Initiate provisioning"},
  1267. { "node-import", "<uuid> <net_idx> <primary> <ele_count> <dev_key>",
  1268. cmd_import_node,
  1269. "Import an externally provisioned remote node"},
  1270. { "list-nodes", NULL, cmd_list_nodes,
  1271. "List remote mesh nodes"},
  1272. { "keys", NULL, cmd_keys,
  1273. "List available keys"},
  1274. { "export-db", NULL, cmd_export_db,
  1275. "Export mesh configuration database"},
  1276. { } },
  1277. };
  1278. static void proxy_added(struct l_dbus_proxy *proxy, void *user_data)
  1279. {
  1280. const char *interface = l_dbus_proxy_get_interface(proxy);
  1281. const char *path = l_dbus_proxy_get_path(proxy);
  1282. bt_shell_printf("Proxy added: %s (%s)\n", interface, path);
  1283. if (!strcmp(interface, MESH_NETWORK_INTERFACE)) {
  1284. net_proxy = proxy;
  1285. /*
  1286. * If mesh network configuration has been read from
  1287. * storage, attach the provisioner/config-client node.
  1288. */
  1289. if (local)
  1290. l_dbus_proxy_method_call(net_proxy, "Attach",
  1291. attach_node_setup,
  1292. attach_node_reply, NULL,
  1293. NULL);
  1294. return;
  1295. }
  1296. if (!strcmp(interface, MESH_MANAGEMENT_INTERFACE)) {
  1297. if (local && local->path) {
  1298. if (!strcmp(local->path, path))
  1299. local->mgmt_proxy = proxy;
  1300. } else
  1301. l_queue_push_tail(node_proxies, proxy);
  1302. return;
  1303. }
  1304. if (!strcmp(interface, MESH_NODE_INTERFACE)) {
  1305. if (local && local->path) {
  1306. if (!strcmp(local->path, path))
  1307. local->proxy = proxy;
  1308. } else
  1309. l_queue_push_tail(node_proxies, proxy);
  1310. }
  1311. }
  1312. static void proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
  1313. {
  1314. const char *interface = l_dbus_proxy_get_interface(proxy);
  1315. const char *path = l_dbus_proxy_get_path(proxy);
  1316. bt_shell_printf("Proxy removed: %s (%s)\n", interface, path);
  1317. if (!strcmp(interface, MESH_NETWORK_INTERFACE)) {
  1318. bt_shell_printf("Mesh removed, terminating.\n");
  1319. l_main_quit();
  1320. return;
  1321. }
  1322. if (!strcmp(interface, MESH_NODE_INTERFACE)) {
  1323. if (local && local->path && !strcmp(local->path, path))
  1324. local->proxy = NULL;
  1325. l_queue_remove(node_proxies, proxy);
  1326. return;
  1327. }
  1328. if (!strcmp(interface, MESH_MANAGEMENT_INTERFACE)) {
  1329. if (local && local->path && !strcmp(local->path, path))
  1330. local->mgmt_proxy = NULL;
  1331. l_queue_remove(node_proxies, proxy);
  1332. }
  1333. }
  1334. static void build_model(struct l_dbus_message_builder *builder, uint16_t mod_id,
  1335. bool pub_enable, bool sub_enable)
  1336. {
  1337. l_dbus_message_builder_enter_struct(builder, "qa{sv}");
  1338. l_dbus_message_builder_append_basic(builder, 'q', &mod_id);
  1339. l_dbus_message_builder_enter_array(builder, "{sv}");
  1340. append_dict_entry_basic(builder, "Subscribe", "b", &sub_enable);
  1341. append_dict_entry_basic(builder, "Publish", "b", &pub_enable);
  1342. l_dbus_message_builder_leave_array(builder);
  1343. l_dbus_message_builder_leave_struct(builder);
  1344. }
  1345. static bool mod_getter(struct l_dbus *dbus,
  1346. struct l_dbus_message *message,
  1347. struct l_dbus_message_builder *builder,
  1348. void *user_data)
  1349. {
  1350. l_dbus_message_builder_enter_array(builder, "(qa{sv})");
  1351. build_model(builder, app.ele.mods[0], false, false);
  1352. build_model(builder, app.ele.mods[1], false, false);
  1353. l_dbus_message_builder_leave_array(builder);
  1354. return true;
  1355. }
  1356. static bool vmod_getter(struct l_dbus *dbus,
  1357. struct l_dbus_message *message,
  1358. struct l_dbus_message_builder *builder,
  1359. void *user_data)
  1360. {
  1361. l_dbus_message_builder_enter_array(builder, "(qqa{sv})");
  1362. l_dbus_message_builder_leave_array(builder);
  1363. return true;
  1364. }
  1365. static bool ele_idx_getter(struct l_dbus *dbus,
  1366. struct l_dbus_message *message,
  1367. struct l_dbus_message_builder *builder,
  1368. void *user_data)
  1369. {
  1370. l_dbus_message_builder_append_basic(builder, 'y', &app.ele.index);
  1371. return true;
  1372. }
  1373. static struct l_dbus_message *dev_msg_recv_call(struct l_dbus *dbus,
  1374. struct l_dbus_message *msg,
  1375. void *user_data)
  1376. {
  1377. struct l_dbus_message_iter iter;
  1378. uint16_t src, idx;
  1379. uint8_t *data;
  1380. uint32_t n;
  1381. bool rmt;
  1382. if (!l_dbus_message_get_arguments(msg, "qbqay", &src, &rmt, &idx,
  1383. &iter)) {
  1384. l_error("Cannot parse received message");
  1385. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1386. }
  1387. if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
  1388. l_error("Cannot parse received message: data");
  1389. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1390. }
  1391. bt_shell_printf("Received dev key message (len %u):", n);
  1392. /* Pass to the configuration client */
  1393. if (cfgcli && cfgcli->ops.recv)
  1394. cfgcli->ops.recv(src, APP_IDX_DEV_REMOTE, data, n);
  1395. return l_dbus_message_new_method_return(msg);
  1396. }
  1397. static void setup_ele_iface(struct l_dbus_interface *iface)
  1398. {
  1399. /* Properties */
  1400. l_dbus_interface_property(iface, "Index", 0, "y", ele_idx_getter,
  1401. NULL);
  1402. l_dbus_interface_property(iface, "VendorModels", 0, "a(qqa{sv})",
  1403. vmod_getter, NULL);
  1404. l_dbus_interface_property(iface, "Models", 0, "a(qa{sv})", mod_getter,
  1405. NULL);
  1406. /* Methods */
  1407. l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
  1408. dev_msg_recv_call, "", "qbqay", "source",
  1409. "remote", "net_index", "data");
  1410. /* TODO: Other methods */
  1411. }
  1412. static struct l_dbus_message *scan_result_call(struct l_dbus *dbus,
  1413. struct l_dbus_message *msg,
  1414. void *user_data)
  1415. {
  1416. struct l_dbus_message_iter iter, opts;
  1417. int16_t rssi;
  1418. uint32_t n;
  1419. uint8_t *prov_data;
  1420. char *str;
  1421. struct unprov_device *dev;
  1422. const char *sig = "naya{sv}";
  1423. if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
  1424. l_error("Cannot parse scan results");
  1425. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1426. }
  1427. if (!l_dbus_message_iter_get_fixed_array(&iter, &prov_data, &n) ||
  1428. n < 16) {
  1429. l_error("Cannot parse scan result: data");
  1430. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1431. }
  1432. bt_shell_printf("Scan result:\n");
  1433. bt_shell_printf("\t" COLOR_GREEN "rssi = %d\n" COLOR_OFF, rssi);
  1434. str = l_util_hexstring_upper(prov_data, 16);
  1435. bt_shell_printf("\t" COLOR_GREEN "UUID = %s\n" COLOR_OFF, str);
  1436. l_free(str);
  1437. if (n >= 18) {
  1438. str = l_util_hexstring_upper(prov_data + 16, 2);
  1439. bt_shell_printf("\t" COLOR_GREEN "OOB = %s\n" COLOR_OFF, str);
  1440. l_free(str);
  1441. }
  1442. if (n >= 22) {
  1443. str = l_util_hexstring_upper(prov_data + 18, 4);
  1444. bt_shell_printf("\t" COLOR_GREEN "URI Hash = %s\n" COLOR_OFF,
  1445. str);
  1446. l_free(str);
  1447. }
  1448. /* TODO: Handle the rest of provisioning data if present */
  1449. dev = l_queue_find(devices, match_device_uuid, prov_data);
  1450. if (!dev) {
  1451. dev = l_new(struct unprov_device, 1);
  1452. memcpy(dev->uuid, prov_data, sizeof(dev->uuid));
  1453. /* TODO: timed self-destructor */
  1454. l_queue_push_tail(devices, dev);
  1455. }
  1456. /* Update with the latest rssi */
  1457. dev->rssi = rssi;
  1458. dev->last_seen = time(NULL);
  1459. return l_dbus_message_new_method_return(msg);
  1460. }
  1461. static struct l_dbus_message *req_prov_call(struct l_dbus *dbus,
  1462. struct l_dbus_message *msg,
  1463. void *user_data)
  1464. {
  1465. uint8_t cnt;
  1466. uint16_t unicast;
  1467. struct l_dbus_message *reply;
  1468. if (!l_dbus_message_get_arguments(msg, "y", &cnt)) {
  1469. l_error("Cannot parse request for prov data");
  1470. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1471. }
  1472. unicast = remote_get_next_unicast(low_addr, high_addr, cnt);
  1473. if (unicast == 0) {
  1474. l_error("Failed to allocate addresses for %u elements\n", cnt);
  1475. return l_dbus_message_new_error(msg,
  1476. "org.freedesktop.DBus.Error."
  1477. "Failed to allocate address", NULL);
  1478. }
  1479. bt_shell_printf("Assign addresses for %u elements\n", cnt);
  1480. reply = l_dbus_message_new_method_return(msg);
  1481. l_dbus_message_set_arguments(reply, "qq", prov_net_idx, unicast);
  1482. return reply;
  1483. }
  1484. static void remove_device(uint8_t *uuid)
  1485. {
  1486. struct unprov_device *dev;
  1487. dev = l_queue_remove_if(devices, match_device_uuid, uuid);
  1488. l_free(dev);
  1489. }
  1490. static struct l_dbus_message *add_node_cmplt_call(struct l_dbus *dbus,
  1491. struct l_dbus_message *msg,
  1492. void *user_data)
  1493. {
  1494. struct l_dbus_message_iter iter;
  1495. int16_t unicast;
  1496. uint8_t cnt;
  1497. uint32_t n;
  1498. uint8_t *uuid;
  1499. if (!prov_in_progress)
  1500. return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  1501. prov_in_progress = false;
  1502. if (!l_dbus_message_get_arguments(msg, "ayqy", &iter, &unicast, &cnt)) {
  1503. l_error("Cannot parse add node complete message");
  1504. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1505. }
  1506. if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
  1507. n != 16) {
  1508. l_error("Cannot parse add node complete message: uuid");
  1509. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1510. }
  1511. remote_add_node(uuid, unicast, cnt, prov_net_idx);
  1512. bt_shell_printf("Provisioning done:\n");
  1513. remote_print_node(unicast);
  1514. remove_device(uuid);
  1515. if (!mesh_db_add_node(uuid, cnt, unicast, prov_net_idx))
  1516. l_error("Failed to store new remote node");
  1517. return l_dbus_message_new_method_return(msg);
  1518. }
  1519. static struct l_dbus_message *add_node_fail_call(struct l_dbus *dbus,
  1520. struct l_dbus_message *msg,
  1521. void *user_data)
  1522. {
  1523. struct l_dbus_message_iter iter;
  1524. uint32_t n;
  1525. uint8_t *uuid;
  1526. char *str, *reason;
  1527. if (!prov_in_progress)
  1528. return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
  1529. prov_in_progress = false;
  1530. if (!l_dbus_message_get_arguments(msg, "ays", &iter, &reason)) {
  1531. l_error("Cannot parse add node failed message");
  1532. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1533. }
  1534. if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
  1535. n != 16) {
  1536. l_error("Cannot parse add node failed message: uuid");
  1537. return l_dbus_message_new_error(msg, dbus_err_args, NULL);
  1538. }
  1539. bt_shell_printf("Provisioning failed:\n");
  1540. str = l_util_hexstring_upper(uuid, 16);
  1541. bt_shell_printf("\t" COLOR_RED "UUID = %s\n" COLOR_OFF, str);
  1542. l_free(str);
  1543. bt_shell_printf("\t" COLOR_RED "%s\n" COLOR_OFF, reason);
  1544. remove_device(uuid);
  1545. return l_dbus_message_new_method_return(msg);
  1546. }
  1547. static void setup_prov_iface(struct l_dbus_interface *iface)
  1548. {
  1549. l_dbus_interface_method(iface, "ScanResult", 0, scan_result_call, "",
  1550. "naya{sv}", "rssi", "data", "options");
  1551. l_dbus_interface_method(iface, "RequestProvData", 0, req_prov_call,
  1552. "qq", "y", "net_index", "unicast", "count");
  1553. l_dbus_interface_method(iface, "AddNodeComplete", 0,
  1554. add_node_cmplt_call, "", "ayqy",
  1555. "uuid", "unicast", "count");
  1556. l_dbus_interface_method(iface, "AddNodeFailed", 0, add_node_fail_call,
  1557. "", "ays", "uuid", "reason");
  1558. }
  1559. static bool cid_getter(struct l_dbus *dbus,
  1560. struct l_dbus_message *message,
  1561. struct l_dbus_message_builder *builder,
  1562. void *user_data)
  1563. {
  1564. l_dbus_message_builder_append_basic(builder, 'q', &app.cid);
  1565. return true;
  1566. }
  1567. static bool pid_getter(struct l_dbus *dbus,
  1568. struct l_dbus_message *message,
  1569. struct l_dbus_message_builder *builder,
  1570. void *user_data)
  1571. {
  1572. l_dbus_message_builder_append_basic(builder, 'q', &app.pid);
  1573. return true;
  1574. }
  1575. static bool vid_getter(struct l_dbus *dbus,
  1576. struct l_dbus_message *message,
  1577. struct l_dbus_message_builder *builder,
  1578. void *user_data)
  1579. {
  1580. l_dbus_message_builder_append_basic(builder, 'q', &app.vid);
  1581. return true;
  1582. }
  1583. static bool crpl_getter(struct l_dbus *dbus,
  1584. struct l_dbus_message *message,
  1585. struct l_dbus_message_builder *builder,
  1586. void *user_data)
  1587. {
  1588. l_dbus_message_builder_append_basic(builder, 'q', &app.crpl);
  1589. return true;
  1590. }
  1591. static void attach_node(void *user_data)
  1592. {
  1593. l_dbus_proxy_method_call(net_proxy, "Attach", attach_node_setup,
  1594. attach_node_reply, NULL,
  1595. NULL);
  1596. }
  1597. static struct l_dbus_message *join_complete(struct l_dbus *dbus,
  1598. struct l_dbus_message *message,
  1599. void *user_data)
  1600. {
  1601. char *str;
  1602. uint64_t tmp;
  1603. if (!l_dbus_message_get_arguments(message, "t", &tmp))
  1604. return l_dbus_message_new_error(message, dbus_err_args, NULL);
  1605. local = l_new(struct meshcfg_node, 1);
  1606. local->token.u64 = l_get_be64(&tmp);
  1607. str = l_util_hexstring(&local->token.u8[0], 8);
  1608. bt_shell_printf("Created new node with token %s\n", str);
  1609. l_free(str);
  1610. if (!mesh_db_create(cfg_fname, local->token.u8,
  1611. "Mesh Config Client Network")) {
  1612. l_free(local);
  1613. local = NULL;
  1614. return l_dbus_message_new_error(message, dbus_err_fail, NULL);
  1615. }
  1616. keys_add_net_key(PRIMARY_NET_IDX);
  1617. mesh_db_add_net_key(PRIMARY_NET_IDX);
  1618. remote_add_node(app.uuid, 0x0001, 1, PRIMARY_NET_IDX);
  1619. mesh_db_add_node(app.uuid, 0x0001, 1, PRIMARY_NET_IDX);
  1620. mesh_db_add_provisioner("BlueZ mesh-cfgclient", app.uuid,
  1621. low_addr, high_addr,
  1622. GROUP_ADDRESS_LOW, GROUP_ADDRESS_HIGH);
  1623. l_idle_oneshot(attach_node, NULL, NULL);
  1624. return l_dbus_message_new_method_return(message);
  1625. }
  1626. static void property_changed(struct l_dbus_proxy *proxy, const char *name,
  1627. struct l_dbus_message *msg, void *user_data)
  1628. {
  1629. const char *interface = l_dbus_proxy_get_interface(proxy);
  1630. const char *path = l_dbus_proxy_get_path(proxy);
  1631. if (strcmp(path, local->path))
  1632. return;
  1633. bt_shell_printf("Property changed: %s %s %s\n", name, path, interface);
  1634. if (!strcmp(interface, "org.bluez.mesh.Node1")) {
  1635. if (!strcmp(name, "IvIndex")) {
  1636. uint32_t ivi;
  1637. if (!l_dbus_message_get_arguments(msg, "u", &ivi))
  1638. return;
  1639. bt_shell_printf("New IV Index: %u\n", ivi);
  1640. iv_index = ivi;
  1641. mesh_db_set_iv_index(ivi);
  1642. remote_clear_rejected_addresses(ivi);
  1643. }
  1644. }
  1645. }
  1646. static void setup_app_iface(struct l_dbus_interface *iface)
  1647. {
  1648. l_dbus_interface_property(iface, "CompanyID", 0, "q", cid_getter,
  1649. NULL);
  1650. l_dbus_interface_property(iface, "VersionID", 0, "q", vid_getter,
  1651. NULL);
  1652. l_dbus_interface_property(iface, "ProductID", 0, "q", pid_getter,
  1653. NULL);
  1654. l_dbus_interface_property(iface, "CRPL", 0, "q", crpl_getter, NULL);
  1655. l_dbus_interface_method(iface, "JoinComplete", 0, join_complete,
  1656. "", "t", "token");
  1657. /* TODO: Methods */
  1658. }
  1659. static bool register_app(void)
  1660. {
  1661. if (!l_dbus_register_interface(dbus, MESH_APPLICATION_INTERFACE,
  1662. setup_app_iface, NULL, false)) {
  1663. l_error("Failed to register interface %s",
  1664. MESH_APPLICATION_INTERFACE);
  1665. return false;
  1666. }
  1667. if (!l_dbus_register_interface(dbus, MESH_PROVISIONER_INTERFACE,
  1668. setup_prov_iface, NULL, false)) {
  1669. l_error("Failed to register interface %s",
  1670. MESH_PROVISIONER_INTERFACE);
  1671. return false;
  1672. }
  1673. if (!l_dbus_register_object(dbus, app.path, NULL, NULL,
  1674. MESH_APPLICATION_INTERFACE, NULL,
  1675. MESH_PROVISIONER_INTERFACE, NULL,
  1676. NULL)) {
  1677. l_error("Failed to register object %s", app.path);
  1678. return false;
  1679. }
  1680. if (!register_agent())
  1681. return false;
  1682. if (!l_dbus_register_interface(dbus, MESH_ELEMENT_INTERFACE,
  1683. setup_ele_iface, NULL, false)) {
  1684. l_error("Failed to register interface %s",
  1685. MESH_ELEMENT_INTERFACE);
  1686. return false;
  1687. }
  1688. if (!l_dbus_register_object(dbus, app.ele.path, NULL, NULL,
  1689. MESH_ELEMENT_INTERFACE, NULL, NULL)) {
  1690. l_error("Failed to register object %s", app.ele.path);
  1691. return false;
  1692. }
  1693. if (!l_dbus_object_add_interface(dbus, app.path,
  1694. L_DBUS_INTERFACE_OBJECT_MANAGER,
  1695. NULL)) {
  1696. l_error("Failed to add interface %s",
  1697. L_DBUS_INTERFACE_OBJECT_MANAGER);
  1698. return false;
  1699. }
  1700. return true;
  1701. }
  1702. static void client_ready(struct l_dbus_client *client, void *user_data)
  1703. {
  1704. bt_shell_printf("D-Bus client ready\n");
  1705. if (!register_app())
  1706. bt_shell_quit(EXIT_FAILURE);
  1707. bt_shell_attach(fileno(stdin));
  1708. }
  1709. static void client_connected(struct l_dbus *dbus, void *user_data)
  1710. {
  1711. bt_shell_printf("D-Bus client connected\n");
  1712. bt_shell_set_prompt(PROMPT_ON);
  1713. }
  1714. static void client_disconnected(struct l_dbus *dbus, void *user_data)
  1715. {
  1716. bt_shell_printf("D-Bus client disconnected, exit\n");
  1717. bt_shell_quit(EXIT_SUCCESS);
  1718. }
  1719. static void ready_callback(void *user_data)
  1720. {
  1721. bt_shell_printf("Connected to D-Bus\n");
  1722. if (!l_dbus_object_manager_enable(dbus, "/"))
  1723. bt_shell_printf("Failed to register the ObjectManager\n");
  1724. }
  1725. static bool setup_cfg_storage(void)
  1726. {
  1727. struct stat st;
  1728. if (!config_opt) {
  1729. char *home;
  1730. char *mesh_dir;
  1731. home = getenv("XDG_CONFIG_HOME");
  1732. if (home) {
  1733. mesh_dir = l_strdup_printf("%s/meshcfg", home);
  1734. } else {
  1735. home = getenv("HOME");
  1736. if (!home) {
  1737. l_error("\"HOME\" not set\n");
  1738. return false;
  1739. }
  1740. mesh_dir = l_strdup_printf("%s/.config/meshcfg", home);
  1741. }
  1742. if (!mesh_dir)
  1743. return false;
  1744. if (stat(mesh_dir, &st) == 0) {
  1745. if (!S_ISDIR(st.st_mode)) {
  1746. l_error("%s not a directory", mesh_dir);
  1747. return false;
  1748. }
  1749. } else if (errno == ENOENT) {
  1750. if (mkdir(mesh_dir, 0700) != 0)
  1751. return false;
  1752. } else {
  1753. perror("Cannot open config directory");
  1754. return false;
  1755. }
  1756. cfg_fname = l_strdup_printf("%s/%s", mesh_dir,
  1757. DEFAULT_CFG_FILE);
  1758. l_free(mesh_dir);
  1759. } else {
  1760. cfg_fname = l_strdup_printf("%s", config_opt);
  1761. }
  1762. if (stat(cfg_fname, &st) == -1) {
  1763. if (errno == ENOENT) {
  1764. l_warn("\nWarning: config file \"%s\" not found",
  1765. cfg_fname);
  1766. return true;
  1767. }
  1768. perror("\nFailed to open config file");
  1769. return false;
  1770. }
  1771. have_config = true;
  1772. return true;
  1773. }
  1774. static bool read_mesh_config(void)
  1775. {
  1776. uint16_t range_l, range_h;
  1777. if (!mesh_db_load(cfg_fname)) {
  1778. l_error("Failed to load config from %s", cfg_fname);
  1779. return false;
  1780. }
  1781. local = l_new(struct meshcfg_node, 1);
  1782. if (!mesh_db_get_token(local->token.u8)) {
  1783. l_error("Failed to read the provisioner's token ID");
  1784. l_error("Check config file %s", cfg_fname);
  1785. l_free(local);
  1786. local = NULL;
  1787. return false;
  1788. }
  1789. l_info("Mesh configuration loaded from %s", cfg_fname);
  1790. if (mesh_db_get_addr_range(&range_l, &range_h)) {
  1791. low_addr = range_l;
  1792. high_addr = range_h;
  1793. }
  1794. iv_index = mesh_db_get_iv_index();
  1795. return true;
  1796. }
  1797. int main(int argc, char *argv[])
  1798. {
  1799. struct l_dbus_client *client;
  1800. uint32_t val;
  1801. int status;
  1802. bt_shell_init(argc, argv, &opt);
  1803. bt_shell_set_menu(&main_menu);
  1804. l_log_set_stderr();
  1805. if (address_opt && sscanf(address_opt, "%04x", &val) == 1)
  1806. low_addr = (uint16_t) val;
  1807. if (low_addr > DEFAULT_MAX_ADDRESS) {
  1808. l_error("Invalid start address");
  1809. bt_shell_cleanup();
  1810. return EXIT_FAILURE;
  1811. }
  1812. if (!low_addr)
  1813. low_addr = DEFAULT_START_ADDRESS;
  1814. if (range_opt && sscanf(address_opt, "%04x", &val) == 1) {
  1815. if (val == 0) {
  1816. l_error("Invalid address range");
  1817. bt_shell_cleanup();
  1818. return EXIT_FAILURE;
  1819. }
  1820. /* Inclusive */
  1821. high_addr = low_addr + val - 1;
  1822. }
  1823. if (!high_addr || high_addr > DEFAULT_MAX_ADDRESS)
  1824. high_addr = DEFAULT_MAX_ADDRESS;
  1825. if (net_idx_opt && sscanf(net_idx_opt, "%04x", &val) == 1)
  1826. prov_net_idx = (uint16_t) val;
  1827. else
  1828. prov_net_idx = DEFAULT_NET_INDEX;
  1829. if (!setup_cfg_storage()) {
  1830. bt_shell_cleanup();
  1831. return EXIT_FAILURE;
  1832. }
  1833. if (have_config && !read_mesh_config()) {
  1834. bt_shell_cleanup();
  1835. return EXIT_FAILURE;
  1836. }
  1837. bt_shell_set_prompt(PROMPT_OFF);
  1838. dbus = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
  1839. l_dbus_set_ready_handler(dbus, ready_callback, NULL, NULL);
  1840. client = l_dbus_client_new(dbus, BLUEZ_MESH_NAME, "/org/bluez/mesh");
  1841. l_dbus_client_set_connect_handler(client, client_connected, NULL, NULL);
  1842. l_dbus_client_set_disconnect_handler(client, client_disconnected, NULL,
  1843. NULL);
  1844. l_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
  1845. property_changed, NULL, NULL);
  1846. l_dbus_client_set_ready_handler(client, client_ready, NULL, NULL);
  1847. node_proxies = l_queue_new();
  1848. devices = l_queue_new();
  1849. status = bt_shell_run();
  1850. l_dbus_client_destroy(client);
  1851. l_dbus_destroy(dbus);
  1852. cfgcli_cleanup();
  1853. return status;
  1854. }