cfgcli.c 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2019-2020 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <stdio.h>
  14. #include <stdbool.h>
  15. #include <ell/ell.h>
  16. #include "src/shared/shell.h"
  17. #include "src/shared/util.h"
  18. #include "mesh/mesh-defs.h"
  19. #include "mesh/util.h"
  20. #include "mesh/crypto.h"
  21. #include "tools/mesh/util.h"
  22. #include "tools/mesh/model.h"
  23. #include "tools/mesh/keys.h"
  24. #include "tools/mesh/mesh-db.h"
  25. #include "tools/mesh/remote.h"
  26. #include "tools/mesh/config-model.h"
  27. #include "tools/mesh/cfgcli.h"
  28. #define MIN_COMPOSITION_LEN 16
  29. #define NO_RESPONSE 0xFFFFFFFF
  30. /* Default timeout for getting a response to a sent config command (seconds) */
  31. #define DEFAULT_TIMEOUT 2
  32. struct cfg_cmd {
  33. uint32_t opcode;
  34. uint32_t rsp;
  35. const char *desc;
  36. };
  37. struct pending_req {
  38. struct l_timeout *timer;
  39. const struct cfg_cmd *cmd;
  40. uint16_t addr;
  41. };
  42. static struct l_queue *requests;
  43. static struct l_queue *groups;
  44. static void *send_data;
  45. static model_send_msg_func_t send_msg;
  46. static delete_remote_func_t mgr_del_remote;
  47. static void *key_data;
  48. static key_send_func_t send_key_msg;
  49. static uint32_t rsp_timeout = DEFAULT_TIMEOUT;
  50. static uint16_t target = UNASSIGNED_ADDRESS;
  51. static uint32_t parms[8];
  52. static struct cfg_cmd cmds[] = {
  53. { OP_APPKEY_ADD, OP_APPKEY_STATUS, "AppKeyAdd" },
  54. { OP_APPKEY_DELETE, OP_APPKEY_STATUS, "AppKeyDelete" },
  55. { OP_APPKEY_GET, OP_APPKEY_LIST, "AppKeyGet" },
  56. { OP_APPKEY_LIST, NO_RESPONSE, "AppKeyList" },
  57. { OP_APPKEY_STATUS, NO_RESPONSE, "AppKeyStatus" },
  58. { OP_APPKEY_UPDATE, OP_APPKEY_STATUS, "AppKeyUpdate" },
  59. { OP_DEV_COMP_GET, OP_DEV_COMP_STATUS, "DeviceCompositionGet" },
  60. { OP_DEV_COMP_STATUS, NO_RESPONSE, "DeviceCompositionStatus" },
  61. { OP_CONFIG_BEACON_GET, OP_CONFIG_BEACON_STATUS, "BeaconGet" },
  62. { OP_CONFIG_BEACON_SET, OP_CONFIG_BEACON_STATUS, "BeaconSet" },
  63. { OP_CONFIG_BEACON_STATUS, NO_RESPONSE, "BeaconStatus" },
  64. { OP_CONFIG_DEFAULT_TTL_GET, OP_CONFIG_DEFAULT_TTL_STATUS,
  65. "DefaultTTLGet" },
  66. { OP_CONFIG_DEFAULT_TTL_SET, OP_CONFIG_DEFAULT_TTL_STATUS,
  67. "DefaultTTLSet" },
  68. { OP_CONFIG_DEFAULT_TTL_STATUS, NO_RESPONSE, "DefaultTTLStatus" },
  69. { OP_CONFIG_FRIEND_GET, OP_CONFIG_FRIEND_STATUS, "FriendGet" },
  70. { OP_CONFIG_FRIEND_SET, OP_CONFIG_FRIEND_STATUS, "FrienSet" },
  71. { OP_CONFIG_FRIEND_STATUS, NO_RESPONSE, "FriendStatus" },
  72. { OP_CONFIG_PROXY_GET, OP_CONFIG_PROXY_STATUS, "ProxyGet" },
  73. { OP_CONFIG_PROXY_SET, OP_CONFIG_PROXY_STATUS, "ProxySet" },
  74. { OP_CONFIG_PROXY_STATUS, NO_RESPONSE, "ProxyStatus" },
  75. { OP_CONFIG_KEY_REFRESH_PHASE_GET, OP_CONFIG_KEY_REFRESH_PHASE_STATUS,
  76. "KeyRefreshPhaseGet" },
  77. { OP_CONFIG_KEY_REFRESH_PHASE_SET, OP_CONFIG_KEY_REFRESH_PHASE_STATUS,
  78. "KeyRefreshPhaseSet" },
  79. { OP_CONFIG_KEY_REFRESH_PHASE_STATUS, NO_RESPONSE,
  80. "KeyRefreshPhaseStatus" },
  81. { OP_CONFIG_MODEL_PUB_GET, OP_CONFIG_MODEL_PUB_STATUS, "ModelPubGet" },
  82. { OP_CONFIG_MODEL_PUB_SET, OP_CONFIG_MODEL_PUB_STATUS, "ModelPubSet" },
  83. { OP_CONFIG_MODEL_PUB_STATUS, NO_RESPONSE, "ModelPubStatus" },
  84. { OP_CONFIG_MODEL_PUB_VIRT_SET, OP_CONFIG_MODEL_PUB_STATUS,
  85. "ModelPubVirtualSet" },
  86. { OP_CONFIG_MODEL_SUB_ADD, OP_CONFIG_MODEL_SUB_STATUS, "ModelSubAdd" },
  87. { OP_CONFIG_MODEL_SUB_DELETE, OP_CONFIG_MODEL_SUB_STATUS,
  88. "ModelSubDelete" },
  89. { OP_CONFIG_MODEL_SUB_DELETE_ALL, OP_CONFIG_MODEL_SUB_STATUS,
  90. "ModelSubDeleteAll" },
  91. { OP_CONFIG_MODEL_SUB_OVERWRITE, OP_CONFIG_MODEL_SUB_STATUS,
  92. "ModelSubOverwrite" },
  93. { OP_CONFIG_MODEL_SUB_STATUS, NO_RESPONSE, "ModelSubStatus" },
  94. { OP_CONFIG_MODEL_SUB_VIRT_ADD, OP_CONFIG_MODEL_SUB_STATUS,
  95. "ModelSubVirtAdd" },
  96. { OP_CONFIG_MODEL_SUB_VIRT_DELETE, OP_CONFIG_MODEL_SUB_STATUS,
  97. "ModelSubVirtDelete" },
  98. { OP_CONFIG_MODEL_SUB_VIRT_OVERWRITE, OP_CONFIG_MODEL_SUB_STATUS,
  99. "ModelSubVirtOverwrite" },
  100. { OP_CONFIG_NETWORK_TRANSMIT_GET, OP_CONFIG_NETWORK_TRANSMIT_STATUS,
  101. "NetworkTransmitGet" },
  102. { OP_CONFIG_NETWORK_TRANSMIT_SET, OP_CONFIG_NETWORK_TRANSMIT_STATUS,
  103. "NetworkTransmitSet" },
  104. { OP_CONFIG_NETWORK_TRANSMIT_STATUS, NO_RESPONSE,
  105. "NetworkTransmitStatus" },
  106. { OP_CONFIG_RELAY_GET, OP_CONFIG_RELAY_STATUS, "RelayGet" },
  107. { OP_CONFIG_RELAY_SET, OP_CONFIG_RELAY_STATUS, "RelaySet" },
  108. { OP_CONFIG_RELAY_STATUS, NO_RESPONSE, "RelayStatus" },
  109. { OP_CONFIG_MODEL_SUB_GET, OP_CONFIG_MODEL_SUB_LIST, "ModelSubGet" },
  110. { OP_CONFIG_MODEL_SUB_LIST, NO_RESPONSE, "ModelSubList" },
  111. { OP_CONFIG_VEND_MODEL_SUB_GET, OP_CONFIG_VEND_MODEL_SUB_LIST,
  112. "VendorModelSubGet" },
  113. { OP_CONFIG_VEND_MODEL_SUB_LIST, NO_RESPONSE, "VendorModelSubList" },
  114. { OP_CONFIG_POLL_TIMEOUT_LIST, OP_CONFIG_POLL_TIMEOUT_STATUS,
  115. "PollTimeoutList" },
  116. { OP_CONFIG_POLL_TIMEOUT_STATUS, NO_RESPONSE, "PollTimeoutStatus" },
  117. { OP_CONFIG_HEARTBEAT_PUB_GET, OP_CONFIG_HEARTBEAT_PUB_STATUS,
  118. "HeartbeatPubGet" },
  119. { OP_CONFIG_HEARTBEAT_PUB_SET, OP_CONFIG_HEARTBEAT_PUB_STATUS,
  120. "HeartbeatPubSet" },
  121. { OP_CONFIG_HEARTBEAT_PUB_STATUS, NO_RESPONSE, "HeartbeatPubStatus" },
  122. { OP_CONFIG_HEARTBEAT_SUB_GET, OP_CONFIG_HEARTBEAT_SUB_STATUS,
  123. "HeartbeatSubGet" },
  124. { OP_CONFIG_HEARTBEAT_SUB_SET, OP_CONFIG_HEARTBEAT_SUB_STATUS,
  125. "HeartbeatSubSet" },
  126. { OP_CONFIG_HEARTBEAT_SUB_STATUS, NO_RESPONSE, "HeartbeatSubStatus" },
  127. { OP_MODEL_APP_BIND, OP_MODEL_APP_STATUS, "ModelAppBind" },
  128. { OP_MODEL_APP_STATUS, NO_RESPONSE, "ModelAppStatus" },
  129. { OP_MODEL_APP_UNBIND, OP_MODEL_APP_STATUS, "ModelAppUnbind" },
  130. { OP_NETKEY_ADD, OP_NETKEY_STATUS, "NetKeyAdd" },
  131. { OP_NETKEY_DELETE, OP_NETKEY_STATUS, "NetKeyDelete" },
  132. { OP_NETKEY_GET, OP_NETKEY_LIST, "NetKeyGet" },
  133. { OP_NETKEY_LIST, NO_RESPONSE, "NetKeyList" },
  134. { OP_NETKEY_STATUS, NO_RESPONSE, "NetKeyStatus" },
  135. { OP_NETKEY_UPDATE, OP_NETKEY_STATUS, "NetKeyUpdate" },
  136. { OP_NODE_IDENTITY_GET, OP_NODE_IDENTITY_STATUS, "NodeIdentityGet" },
  137. { OP_NODE_IDENTITY_SET, OP_NODE_IDENTITY_STATUS, "NodeIdentitySet" },
  138. { OP_NODE_IDENTITY_STATUS, NO_RESPONSE, "NodeIdentityStatus" },
  139. { OP_NODE_RESET, OP_NODE_RESET_STATUS, "NodeReset" },
  140. { OP_NODE_RESET_STATUS, NO_RESPONSE, "NodeResetStatus" },
  141. { OP_MODEL_APP_GET, OP_MODEL_APP_LIST, "ModelAppGet" },
  142. { OP_MODEL_APP_LIST, NO_RESPONSE, "ModelAppList" },
  143. { OP_VEND_MODEL_APP_GET, OP_VEND_MODEL_APP_LIST, "VendorModelAppGet" },
  144. { OP_VEND_MODEL_APP_LIST, NO_RESPONSE, "VendorModelAppList" }
  145. };
  146. static const struct cfg_cmd *get_cmd(uint32_t opcode)
  147. {
  148. uint32_t n;
  149. for (n = 0; n < L_ARRAY_SIZE(cmds); n++) {
  150. if (opcode == cmds[n].opcode)
  151. return &cmds[n];
  152. }
  153. return NULL;
  154. }
  155. static const char *opcode_str(uint32_t opcode)
  156. {
  157. const struct cfg_cmd *cmd;
  158. cmd = get_cmd(opcode);
  159. if (!cmd)
  160. return "Unknown";
  161. return cmd->desc;
  162. }
  163. static void reset_remote_node(uint16_t addr)
  164. {
  165. uint8_t ele_cnt = remote_del_node(addr);
  166. bt_shell_printf("Remote removed (primary %4.4x)\n", addr);
  167. if (ele_cnt && mgr_del_remote)
  168. mgr_del_remote(addr, ele_cnt);
  169. }
  170. static void free_request(void *a)
  171. {
  172. struct pending_req *req = a;
  173. l_timeout_remove(req->timer);
  174. l_free(req);
  175. }
  176. static struct pending_req *get_req_by_rsp(uint16_t addr, uint32_t rsp)
  177. {
  178. const struct l_queue_entry *entry;
  179. entry = l_queue_get_entries(requests);
  180. for (; entry; entry = entry->next) {
  181. struct pending_req *req = entry->data;
  182. if (req->addr == addr && req->cmd->rsp == rsp)
  183. return req;
  184. }
  185. return NULL;
  186. }
  187. static void wait_rsp_timeout(struct l_timeout *timeout, void *user_data)
  188. {
  189. struct pending_req *req = user_data;
  190. bt_shell_printf("No response for \"%s\" from %4.4x\n",
  191. req->cmd->desc, req->addr);
  192. /* Node reset case: delete the remote even if there is no response */
  193. if (req->cmd->opcode == OP_NODE_RESET)
  194. reset_remote_node(req->addr);
  195. l_queue_remove(requests, req);
  196. free_request(req);
  197. }
  198. static void add_request(uint32_t opcode)
  199. {
  200. struct pending_req *req;
  201. const struct cfg_cmd *cmd;
  202. cmd = get_cmd(opcode);
  203. if (!cmd)
  204. return;
  205. req = l_new(struct pending_req, 1);
  206. req->cmd = cmd;
  207. req->addr = target;
  208. req->timer = l_timeout_create(rsp_timeout,
  209. wait_rsp_timeout, req, NULL);
  210. l_queue_push_tail(requests, req);
  211. }
  212. static uint32_t print_mod_id(uint8_t *data, bool vendor, const char *offset)
  213. {
  214. uint32_t mod_id;
  215. if (!vendor) {
  216. mod_id = get_le16(data);
  217. bt_shell_printf("%sModel ID\t%4.4x \"%s\"\n",
  218. offset, mod_id, sig_model_string(mod_id));
  219. mod_id = VENDOR_ID_MASK | mod_id;
  220. } else {
  221. mod_id = get_le16(data + 2);
  222. bt_shell_printf("%sModel ID\t%4.4x %4.4x\n", offset,
  223. get_le16(data), mod_id);
  224. mod_id = get_le16(data) << 16 | mod_id;
  225. }
  226. return mod_id;
  227. }
  228. static void print_composition(uint8_t *data, uint16_t len)
  229. {
  230. uint16_t features;
  231. int i = 0;
  232. bt_shell_printf("Received composion:\n");
  233. /* skip page -- We only support Page Zero */
  234. data++;
  235. len--;
  236. bt_shell_printf("\tCID: %4.4x", get_le16(&data[0]));
  237. bt_shell_printf("\tPID: %4.4x", get_le16(&data[2]));
  238. bt_shell_printf("\tVID: %4.4x", get_le16(&data[4]));
  239. bt_shell_printf("\tCRPL: %4.4x", get_le16(&data[6]));
  240. features = get_le16(&data[8]);
  241. data += 10;
  242. len -= 10;
  243. bt_shell_printf("\tFeature support:\n");
  244. bt_shell_printf("\t\trelay: %s\n", (features & FEATURE_RELAY) ?
  245. "yes" : "no");
  246. bt_shell_printf("\t\tproxy: %s\n", (features & FEATURE_PROXY) ?
  247. "yes" : "no");
  248. bt_shell_printf("\t\tfriend: %s\n", (features & FEATURE_FRIEND) ?
  249. "yes" : "no");
  250. bt_shell_printf("\t\tlpn: %s\n", (features & FEATURE_LPN) ?
  251. "yes" : "no");
  252. while (len) {
  253. uint8_t m, v;
  254. bt_shell_printf("\t Element %d:\n", i);
  255. bt_shell_printf("\t\tlocation: %4.4x\n", get_le16(data));
  256. data += 2;
  257. len -= 2;
  258. m = *data++;
  259. v = *data++;
  260. len -= 2;
  261. if (m)
  262. bt_shell_printf("\t\tSIG defined models:\n");
  263. while (len >= 2 && m--) {
  264. print_mod_id(data, false, "\t\t ");
  265. data += 2;
  266. len -= 2;
  267. }
  268. if (v)
  269. bt_shell_printf("\t\t Vendor defined models:\n");
  270. while (len >= 4 && v--) {
  271. print_mod_id(data, true, "\t\t ");
  272. data += 4;
  273. len -= 4;
  274. }
  275. i++;
  276. }
  277. }
  278. static void print_pub(uint16_t ele_addr, uint32_t mod_id,
  279. struct model_pub *pub)
  280. {
  281. bt_shell_printf("\tElement: %4.4x\n", ele_addr);
  282. bt_shell_printf("\tPub Addr: %4.4x\n", pub->u.addr);
  283. if (mod_id < VENDOR_ID_MASK)
  284. bt_shell_printf("\tModel: %8.8x\n", mod_id);
  285. else
  286. bt_shell_printf("\tModel: %4.4x\n",
  287. (uint16_t) (mod_id & ~VENDOR_ID_MASK));
  288. bt_shell_printf("\tApp Key Idx: %u (0x%3.3x)\n", pub->app_idx,
  289. pub->app_idx);
  290. bt_shell_printf("\tTTL: %2.2x\n", pub->ttl);
  291. }
  292. static void print_sub_list(uint16_t addr, bool is_vendor, uint8_t *data,
  293. uint16_t len)
  294. {
  295. uint16_t i;
  296. bt_shell_printf("\nNode %4.4x Subscription List status %s\n",
  297. addr, mesh_status_str(data[0]));
  298. bt_shell_printf("Element Addr\t%4.4x\n", get_le16(data + 1));
  299. print_mod_id(data + 3, is_vendor, "");
  300. i = (is_vendor ? 7 : 5);
  301. bt_shell_printf("Subscriptions:\n");
  302. for (; i < len; i += 2)
  303. bt_shell_printf("\t\t%4.4x\n ", get_le16(data + i));
  304. }
  305. static void print_appkey_list(uint16_t len, uint8_t *data)
  306. {
  307. uint16_t app_idx;
  308. bt_shell_printf("AppKeys:\n");
  309. while (len >= 3) {
  310. app_idx = l_get_le16(data) & 0xfff;
  311. bt_shell_printf("\t%u (0x%3.3x)\n", app_idx, app_idx);
  312. app_idx = l_get_le16(data + 1) >> 4;
  313. bt_shell_printf("\t%u (0x%3.3x)\n", app_idx, app_idx);
  314. data += 3;
  315. len -= 3;
  316. }
  317. if (len == 2) {
  318. app_idx = l_get_le16(data) & 0xfff;
  319. bt_shell_printf("\t %u (0x%3.3x)\n", app_idx, app_idx);
  320. }
  321. }
  322. static bool match_group_addr(const void *a, const void *b)
  323. {
  324. const struct mesh_group *grp = a;
  325. uint16_t addr = L_PTR_TO_UINT(b);
  326. return grp->addr == addr;
  327. }
  328. static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
  329. uint16_t len)
  330. {
  331. uint32_t opcode, mod_id;
  332. const struct cfg_cmd *cmd;
  333. uint16_t app_idx, net_idx, addr, ele_addr, features;
  334. struct mesh_group *grp;
  335. struct model_pub pub;
  336. int n;
  337. struct pending_req *req;
  338. bool saved = false;
  339. if (mesh_opcode_get(data, len, &opcode, &n)) {
  340. len -= n;
  341. data += n;
  342. } else
  343. return false;
  344. bt_shell_printf("Received %s (len %u)\n", opcode_str(opcode), len);
  345. req = get_req_by_rsp(src, opcode);
  346. if (req) {
  347. cmd = req->cmd;
  348. l_queue_remove(requests, req);
  349. free_request(req);
  350. } else
  351. cmd = NULL;
  352. switch (opcode) {
  353. default:
  354. return false;
  355. case OP_DEV_COMP_STATUS:
  356. if (len < MIN_COMPOSITION_LEN)
  357. return true;
  358. print_composition(data, len);
  359. saved = mesh_db_node_set_composition(src, data, len);
  360. if (saved)
  361. remote_set_composition(src, true);
  362. break;
  363. case OP_APPKEY_STATUS:
  364. if (len != 4)
  365. return true;
  366. bt_shell_printf("Node %4.4x AppKey status %s\n", src,
  367. mesh_status_str(data[0]));
  368. net_idx = get_le16(data + 1) & 0xfff;
  369. app_idx = get_le16(data + 2) >> 4;
  370. bt_shell_printf("NetKey\t%u (0x%3.3x)\n", net_idx, net_idx);
  371. bt_shell_printf("AppKey\t%u (0x%3.3x)\n", app_idx, app_idx);
  372. if (data[0] != MESH_STATUS_SUCCESS)
  373. return true;
  374. if (!cmd)
  375. return true;
  376. if (cmd->opcode == OP_APPKEY_ADD)
  377. saved = remote_add_app_key(src, app_idx, true);
  378. else if (cmd->opcode == OP_APPKEY_DELETE)
  379. saved = remote_del_app_key(src, app_idx);
  380. else if (cmd->opcode == OP_APPKEY_UPDATE)
  381. saved = remote_update_app_key(src, app_idx, true, true);
  382. break;
  383. case OP_APPKEY_LIST:
  384. if (len < 3)
  385. return true;
  386. bt_shell_printf("AppKey List (node %4.4x) Status %s\n",
  387. src, mesh_status_str(data[0]));
  388. net_idx = l_get_le16(&data[1]);
  389. bt_shell_printf("NetKey %u (0x%3.3x)\n", net_idx, net_idx);
  390. len -= 3;
  391. if (data[0] != MESH_STATUS_SUCCESS)
  392. return true;
  393. data += 3;
  394. print_appkey_list(len, data);
  395. return true;
  396. case OP_NETKEY_STATUS:
  397. if (len != 3)
  398. return true;
  399. bt_shell_printf("Node %4.4x NetKey status %s\n", src,
  400. mesh_status_str(data[0]));
  401. net_idx = get_le16(data + 1) & 0xfff;
  402. bt_shell_printf("\tNetKey %u (0x%3.3x)\n", net_idx, net_idx);
  403. if (data[0] != MESH_STATUS_SUCCESS)
  404. return true;
  405. if (!cmd)
  406. return true;
  407. if (cmd->opcode == OP_NETKEY_ADD)
  408. saved = remote_add_net_key(src, net_idx, true);
  409. else if (cmd->opcode == OP_NETKEY_DELETE)
  410. saved = remote_del_net_key(src, net_idx);
  411. else if (cmd->opcode == OP_NETKEY_UPDATE)
  412. saved = remote_update_net_key(src, net_idx, true, true);
  413. break;
  414. case OP_NETKEY_LIST:
  415. if (len < 2)
  416. return true;
  417. bt_shell_printf("NetKey List (node %4.4x):\n", src);
  418. while (len >= 3) {
  419. net_idx = l_get_le16(data) & 0xfff;
  420. bt_shell_printf("\t%u (0x%3.3x)\n", net_idx, net_idx);
  421. net_idx = l_get_le16(data + 1) >> 4;
  422. bt_shell_printf("\t%u (0x%3.3x)\n", net_idx, net_idx);
  423. data += 3;
  424. len -= 3;
  425. }
  426. if (len == 2) {
  427. net_idx = l_get_le16(data) & 0xfff;
  428. bt_shell_printf("\t %u (0x%3.3x)\n", net_idx, net_idx);
  429. }
  430. return true;
  431. case OP_CONFIG_KEY_REFRESH_PHASE_STATUS:
  432. if (len != 4)
  433. return true;
  434. bt_shell_printf("Node %4.4x Key Refresh Phase status %s\n", src,
  435. mesh_status_str(data[0]));
  436. net_idx = get_le16(data + 1) & 0xfff;
  437. bt_shell_printf("\tNetKey %u (0x%3.3x)\n", net_idx, net_idx);
  438. bt_shell_printf("\tKR Phase %2.2x\n", data[3]);
  439. if (data[0] != MESH_STATUS_SUCCESS)
  440. return true;
  441. if (data[3] != KEY_REFRESH_PHASE_NONE)
  442. return true;
  443. saved = remote_finish_key_refresh(src, net_idx);
  444. break;
  445. case OP_MODEL_APP_STATUS:
  446. if (len != 7 && len != 9)
  447. return true;
  448. bt_shell_printf("Node %4.4x: Model App status %s\n", src,
  449. mesh_status_str(data[0]));
  450. addr = get_le16(data + 1);
  451. app_idx = get_le16(data + 3);
  452. bt_shell_printf("Element Addr\t%4.4x\n", addr);
  453. mod_id = print_mod_id(data + 5, len == 9, "");
  454. bt_shell_printf("AppIdx\t\t%u (0x%3.3x)\n ", app_idx, app_idx);
  455. if (data[0] != MESH_STATUS_SUCCESS || !cmd)
  456. return true;
  457. if (cmd->opcode == OP_MODEL_APP_BIND)
  458. saved = mesh_db_node_model_bind(src, addr, len == 9,
  459. mod_id, app_idx);
  460. else
  461. saved = mesh_db_node_model_unbind(src, addr, len == 9,
  462. mod_id, app_idx);
  463. break;
  464. case OP_NODE_IDENTITY_STATUS:
  465. if (len != 4)
  466. return true;
  467. bt_shell_printf("NetIdx %4.4x, NodeIdState 0x%02x, status %s\n",
  468. get_le16(data + 1), data[3],
  469. mesh_status_str(data[0]));
  470. return true;
  471. case OP_CONFIG_BEACON_STATUS:
  472. if (len != 1)
  473. return true;
  474. bt_shell_printf("Node %4.4x: Config Beacon Status 0x%02x\n",
  475. src, data[0]);
  476. saved = mesh_db_node_set_beacon(src, data[0] != 0);
  477. break;
  478. case OP_CONFIG_RELAY_STATUS:
  479. if (len != 2)
  480. return true;
  481. bt_shell_printf("Node %4.4x: Relay 0x%02x, cnt %d, steps %d\n",
  482. src, data[0], data[1] & 0x7, data[1] >> 3);
  483. saved = mesh_db_node_set_relay(src, data[0], data[1] & 7,
  484. ((data[1] >> 3) + 1) * 10);
  485. break;
  486. case OP_CONFIG_PROXY_STATUS:
  487. if (len != 1)
  488. return true;
  489. bt_shell_printf("Node %4.4x Proxy state 0x%02x\n",
  490. src, data[0]);
  491. saved = mesh_db_node_set_proxy(src, data[0]);
  492. break;
  493. case OP_CONFIG_DEFAULT_TTL_STATUS:
  494. if (len != 1)
  495. return true;
  496. bt_shell_printf("Node %4.4x Default TTL %d\n", src, data[0]);
  497. saved = mesh_db_node_set_ttl(src, data[0]);
  498. break;
  499. case OP_CONFIG_MODEL_PUB_STATUS:
  500. if (len != 12 && len != 14)
  501. return true;
  502. bt_shell_printf("\nNode %4.4x Publication status %s\n",
  503. src, mesh_status_str(data[0]));
  504. if (data[0] != MESH_STATUS_SUCCESS)
  505. return true;
  506. ele_addr = get_le16(data + 1);
  507. mod_id = print_mod_id(data + 10, len == 14, "");
  508. pub.u.addr = get_le16(data + 3);
  509. pub.app_idx = get_le16(data + 5);
  510. pub.cred = ((pub.app_idx & 0x1000) != 0);
  511. pub.app_idx &= 0x3ff;
  512. pub.ttl = data[7];
  513. pub.prd_steps = (data[8] & 0x3f);
  514. print_pub(ele_addr, mod_id, &pub);
  515. switch (data[8] >> 6) {
  516. case 0:
  517. pub.prd_res = 100;
  518. break;
  519. case 2:
  520. pub.prd_res = 10;
  521. break;
  522. case 1:
  523. pub.prd_res = 10000;
  524. break;
  525. case 3:
  526. pub.prd_res = 600000;
  527. break;
  528. }
  529. pub.rtx_cnt = data[9] & 0x7;
  530. pub.rtx_interval = ((data[9] >> 3) + 1) * 50;
  531. bt_shell_printf("Rexmit count\t%d\n", pub.rtx_cnt);
  532. bt_shell_printf("Rexmit steps\t%d\n", pub.rtx_interval);
  533. if (IS_VIRTUAL(pub.u.addr)) {
  534. grp = l_queue_find(groups, match_group_addr,
  535. L_UINT_TO_PTR(pub.u.addr));
  536. if (!grp) {
  537. bt_shell_printf("Unknown virtual group\n");
  538. return true;
  539. }
  540. memcpy(pub.u.label, grp->label, sizeof(pub.u.label));
  541. }
  542. saved = mesh_db_node_model_set_pub(src, ele_addr, len == 14,
  543. mod_id, &pub,
  544. IS_VIRTUAL(pub.u.addr));
  545. break;
  546. /* Per Mesh Profile 4.3.2.19 */
  547. case OP_CONFIG_MODEL_SUB_STATUS:
  548. if (len != 7 && len != 9)
  549. return true;
  550. bt_shell_printf("\nNode %4.4x Subscription status %s\n",
  551. src, mesh_status_str(data[0]));
  552. ele_addr = get_le16(data + 1);
  553. addr = get_le16(data + 3);
  554. bt_shell_printf("Element Addr\t%4.4x\n", ele_addr);
  555. mod_id = print_mod_id(data + 5, len == 9, "");
  556. bt_shell_printf("Subscr Addr\t%4.4x\n", addr);
  557. grp = l_queue_find(groups, match_group_addr,
  558. L_UINT_TO_PTR(addr));
  559. if (data[0] != MESH_STATUS_SUCCESS || !cmd)
  560. return true;
  561. switch (cmd->opcode) {
  562. default:
  563. return true;
  564. case OP_CONFIG_MODEL_SUB_ADD:
  565. saved = mesh_db_node_model_add_sub(src, ele_addr,
  566. len == 9, mod_id, addr);
  567. break;
  568. case OP_CONFIG_MODEL_SUB_DELETE:
  569. saved = mesh_db_node_model_del_sub(src, ele_addr,
  570. len == 9, mod_id, addr);
  571. break;
  572. case OP_CONFIG_MODEL_SUB_OVERWRITE:
  573. saved = mesh_db_node_model_overwrt_sub(src, ele_addr,
  574. len == 9, mod_id, addr);
  575. break;
  576. case OP_CONFIG_MODEL_SUB_DELETE_ALL:
  577. saved = mesh_db_node_model_del_sub_all(src, ele_addr,
  578. len == 9, mod_id);
  579. break;
  580. case OP_CONFIG_MODEL_SUB_VIRT_ADD:
  581. if (grp)
  582. saved = mesh_db_node_model_add_sub_virt(src,
  583. ele_addr, len == 9,
  584. mod_id, grp->label);
  585. break;
  586. case OP_CONFIG_MODEL_SUB_VIRT_DELETE:
  587. if (grp)
  588. saved = mesh_db_node_model_del_sub_virt(src,
  589. ele_addr, len == 9,
  590. mod_id, grp->label);
  591. break;
  592. case OP_CONFIG_MODEL_SUB_VIRT_OVERWRITE:
  593. if (grp)
  594. saved = mesh_db_node_model_overwrt_sub_virt(src,
  595. ele_addr, len == 9,
  596. mod_id, grp->label);
  597. break;
  598. }
  599. break;
  600. /* Per Mesh Profile 4.3.2.27 */
  601. case OP_CONFIG_MODEL_SUB_LIST:
  602. if (len < 5)
  603. return true;
  604. print_sub_list(src, false, data, len);
  605. return true;
  606. case OP_CONFIG_VEND_MODEL_SUB_LIST:
  607. if (len < 7)
  608. return true;
  609. print_sub_list(src, true, data, len);
  610. return true;
  611. /* Per Mesh Profile 4.3.2.50 */
  612. case OP_MODEL_APP_LIST:
  613. if (len < 5)
  614. return true;
  615. bt_shell_printf("\nNode %4.4x Model AppIdx status %s\n",
  616. src, mesh_status_str(data[0]));
  617. bt_shell_printf("Element Addr\t%4.4x\n", get_le16(data + 1));
  618. bt_shell_printf("Model ID\t%4.4x\n", get_le16(data + 3));
  619. data += 5;
  620. len -= 5;
  621. print_appkey_list(len, data);
  622. return true;
  623. case OP_VEND_MODEL_APP_LIST:
  624. if (len < 7)
  625. return true;
  626. bt_shell_printf("\nNode %4.4x Vendor Model AppIdx status %s\n",
  627. src, mesh_status_str(data[0]));
  628. if (data[0] != MESH_STATUS_SUCCESS)
  629. return true;
  630. bt_shell_printf("Element Addr\t%4.4x\n", get_le16(data + 1));
  631. print_mod_id(data + 3, true, "");
  632. data += 7;
  633. len -= 7;
  634. print_appkey_list(len, data);
  635. return true;
  636. /* Per Mesh Profile 4.3.2.63 */
  637. case OP_CONFIG_HEARTBEAT_PUB_STATUS:
  638. if (len != 10)
  639. return true;
  640. bt_shell_printf("\nNode %4.4x Heartbeat publish status %s\n",
  641. src, mesh_status_str(data[0]));
  642. if (data[0] != MESH_STATUS_SUCCESS)
  643. return true;
  644. addr = get_le16(data + 1);
  645. bt_shell_printf("Destination\t%4.4x\n", addr);
  646. bt_shell_printf("CountLog\t\t%2.2x\n", data[3]);
  647. bt_shell_printf("PeriodLog\t\t%2.2x\n", data[4]);
  648. bt_shell_printf("TTL\t\t%2.2x\n", data[5]);
  649. features = get_le16(data + 6);
  650. bt_shell_printf("Features\t%4.4x\n", features);
  651. net_idx = get_le16(data + 8);
  652. bt_shell_printf("Net_Idx\t%u (0x%3.3x)\n", net_idx, net_idx);
  653. saved = mesh_db_node_set_hb_pub(src, addr, net_idx, data[4],
  654. data[5], features);
  655. break;
  656. /* Per Mesh Profile 4.3.2.66 */
  657. case OP_CONFIG_HEARTBEAT_SUB_STATUS:
  658. if (len != 9)
  659. return true;
  660. bt_shell_printf("\nNode %4.4x Heartbeat subscribe status %s\n",
  661. src, mesh_status_str(data[0]));
  662. if (data[0] != MESH_STATUS_SUCCESS)
  663. return true;
  664. ele_addr = get_le16(data + 1);
  665. bt_shell_printf("Source\t\t%4.4x\n", ele_addr);
  666. addr = get_le16(data + 3);
  667. bt_shell_printf("Destination\t%4.4x\n", addr);
  668. bt_shell_printf("Period\t\t%2.2x\n", data[5]);
  669. bt_shell_printf("Count\t\t%2.2x\n", data[6]);
  670. bt_shell_printf("Min Hops\t%2.2x\n", data[7]);
  671. bt_shell_printf("Max Hops\t%2.2x\n", data[8]);
  672. saved = mesh_db_node_set_hb_sub(src, ele_addr, addr);
  673. break;
  674. /* Per Mesh Profile 4.3.2.71 */
  675. case OP_CONFIG_NETWORK_TRANSMIT_STATUS:
  676. if (len != 1)
  677. return true;
  678. bt_shell_printf("Node %4.4x: Net transmit cnt %d, steps %d\n",
  679. src, data[0] & 7, data[0] >> 3);
  680. saved = mesh_db_node_set_net_transmit(src, data[0] & 7,
  681. ((data[0] >> 3) + 1) * 10);
  682. break;
  683. /* Per Mesh Profile 4.3.2.54 */
  684. case OP_NODE_RESET_STATUS:
  685. bt_shell_printf("Node %4.4x is reset\n", src);
  686. reset_remote_node(src);
  687. return true;
  688. /* Per Mesh Profile 4.3.2.57 */
  689. case OP_CONFIG_FRIEND_STATUS:
  690. if (len != 1)
  691. return true;
  692. bt_shell_printf("Node %4.4x Friend state 0x%02x\n",
  693. src, data[0]);
  694. saved = mesh_db_node_set_friend(src, data[0]);
  695. break;
  696. }
  697. if (!saved)
  698. bt_shell_printf("Warning: Configuration not updated\n");
  699. return true;
  700. }
  701. static uint16_t put_model_id(uint8_t *buf, uint32_t *args, bool vendor)
  702. {
  703. uint16_t n = 2;
  704. if (vendor) {
  705. put_le16(args[1], buf);
  706. buf += 2;
  707. n = 4;
  708. }
  709. put_le16(args[0], buf);
  710. return n;
  711. }
  712. static uint32_t read_input_parameters(int argc, char *argv[])
  713. {
  714. uint32_t i;
  715. if (!argc)
  716. return 0;
  717. --argc;
  718. ++argv;
  719. if (!argc || argv[0][0] == '\0')
  720. return 0;
  721. for (i = 0; i < L_ARRAY_SIZE(parms) && i < (uint32_t) argc; i++) {
  722. if (sscanf(argv[i], "%x", &parms[i]) != 1)
  723. break;
  724. }
  725. return i;
  726. }
  727. static int compare_group_addr(const void *a, const void *b, void *user_data)
  728. {
  729. const struct mesh_group *grp0 = a;
  730. const struct mesh_group *grp1 = b;
  731. if (grp0->addr < grp1->addr)
  732. return -1;
  733. if (grp0->addr > grp1->addr)
  734. return 1;
  735. return 0;
  736. }
  737. static void print_virtual_not_found(uint16_t addr)
  738. {
  739. bt_shell_printf("Virtual group with hash %4.4x not found\n", addr);
  740. bt_shell_printf("To see available, use \"group-list\"\n");
  741. bt_shell_printf("To create new, use \"virt-add\"\n");
  742. }
  743. static struct mesh_group *add_group(uint16_t addr)
  744. {
  745. struct mesh_group *grp;
  746. if (!IS_GROUP(addr) || addr >= FIXED_GROUP_LOW)
  747. return NULL;
  748. grp = l_queue_find(groups, match_group_addr, L_UINT_TO_PTR(addr));
  749. if (grp)
  750. return grp;
  751. grp = l_new(struct mesh_group, 1);
  752. grp->addr = addr;
  753. l_queue_insert(groups, grp, compare_group_addr, NULL);
  754. mesh_db_add_group(grp);
  755. return grp;
  756. }
  757. static void cmd_timeout_set(int argc, char *argv[])
  758. {
  759. if (read_input_parameters(argc, argv) != 1)
  760. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  761. rsp_timeout = parms[0];
  762. bt_shell_printf("Timeout to wait for remote node's response: %d secs\n",
  763. rsp_timeout);
  764. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  765. }
  766. static void cmd_dst_set(int argc, char *argv[])
  767. {
  768. uint32_t dst;
  769. char *end;
  770. dst = strtol(argv[1], &end, 16);
  771. if (end != (argv[1] + 4)) {
  772. bt_shell_printf("Bad unicast address %s: "
  773. "expected format 4 digit hex\n", argv[1]);
  774. target = UNASSIGNED_ADDRESS;
  775. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  776. }
  777. bt_shell_printf("Configuring node %4.4x\n", dst);
  778. target = dst;
  779. set_menu_prompt("config", argv[1]);
  780. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  781. }
  782. static bool config_send(uint8_t *buf, uint16_t len, uint32_t opcode)
  783. {
  784. const struct cfg_cmd *cmd;
  785. bool res;
  786. if (IS_UNASSIGNED(target)) {
  787. bt_shell_printf("Destination not set\n");
  788. return false;
  789. }
  790. cmd = get_cmd(opcode);
  791. if (!cmd)
  792. return false;
  793. if (get_req_by_rsp(target, cmd->rsp)) {
  794. bt_shell_printf("Another command is pending\n");
  795. return false;
  796. }
  797. res = send_msg(send_data, target, APP_IDX_DEV_REMOTE, buf, len);
  798. if (!res)
  799. bt_shell_printf("Failed to send \"%s\"\n", opcode_str(opcode));
  800. if (cmd->rsp != NO_RESPONSE)
  801. add_request(opcode);
  802. return res;
  803. }
  804. static void cmd_default(uint32_t opcode)
  805. {
  806. uint16_t n;
  807. uint8_t msg[32];
  808. n = mesh_opcode_set(opcode, msg);
  809. if (!config_send(msg, n, opcode))
  810. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  811. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  812. }
  813. static void cmd_composition_get(int argc, char *argv[])
  814. {
  815. uint16_t n;
  816. uint8_t msg[32];
  817. n = mesh_opcode_set(OP_DEV_COMP_GET, msg);
  818. /* By default, use page 0 */
  819. msg[n++] = (read_input_parameters(argc, argv) == 1) ? parms[0] : 0;
  820. if (!config_send(msg, n, OP_DEV_COMP_GET))
  821. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  822. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  823. }
  824. static void cmd_netkey_del(int argc, char *argv[])
  825. {
  826. uint16_t n;
  827. uint8_t msg[32];
  828. if (IS_UNASSIGNED(target)) {
  829. bt_shell_printf("Destination not set\n");
  830. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  831. }
  832. n = mesh_opcode_set(OP_NETKEY_DELETE, msg);
  833. if (read_input_parameters(argc, argv) != 1) {
  834. bt_shell_printf("Bad arguments %s\n", argv[1]);
  835. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  836. }
  837. put_le16(parms[0], msg + n);
  838. n += 2;
  839. if (!config_send(msg, n, OP_NETKEY_DELETE))
  840. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  841. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  842. }
  843. static void cmd_kr_phase_get(int argc, char *argv[])
  844. {
  845. uint16_t n;
  846. uint8_t msg[32];
  847. if (IS_UNASSIGNED(target)) {
  848. bt_shell_printf("Destination not set\n");
  849. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  850. }
  851. n = mesh_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_GET, msg);
  852. if (read_input_parameters(argc, argv) != 1)
  853. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  854. put_le16(parms[0], msg + n);
  855. n += 2;
  856. if (!config_send(msg, n, OP_CONFIG_KEY_REFRESH_PHASE_GET))
  857. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  858. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  859. }
  860. static void cmd_kr_phase_set(int argc, char *argv[])
  861. {
  862. uint16_t n;
  863. uint8_t msg[32];
  864. uint8_t phase;
  865. if (IS_UNASSIGNED(target)) {
  866. bt_shell_printf("Destination not set\n");
  867. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  868. }
  869. n = mesh_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_SET, msg);
  870. if (read_input_parameters(argc, argv) != 2)
  871. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  872. if (parms[1] != KEY_REFRESH_PHASE_TWO &&
  873. parms[1] != KEY_REFRESH_PHASE_THREE) {
  874. bt_shell_printf("Invalid KR transition value %u\n", parms[1]);
  875. bt_shell_printf("Allowed values: 2 or 3\n");
  876. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  877. }
  878. if (!keys_get_net_key_phase((uint16_t) parms[0], &phase)) {
  879. bt_shell_printf("Subnet KR state not found\n");
  880. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  881. }
  882. if (phase != (parms[1] % KEY_REFRESH_PHASE_THREE)) {
  883. bt_shell_printf("Subnet's phase must be updated first!\n");
  884. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  885. }
  886. put_le16(parms[0], msg + n);
  887. n += 2;
  888. msg[n++] = parms[1];
  889. if (!config_send(msg, n, OP_CONFIG_KEY_REFRESH_PHASE_SET))
  890. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  891. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  892. }
  893. static void cmd_appkey_del(int argc, char *argv[])
  894. {
  895. uint16_t n;
  896. uint8_t msg[32];
  897. uint16_t app_idx, net_idx;
  898. if (IS_UNASSIGNED(target)) {
  899. bt_shell_printf("Destination not set\n");
  900. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  901. }
  902. n = mesh_opcode_set(OP_APPKEY_DELETE, msg);
  903. if (read_input_parameters(argc, argv) != 1) {
  904. bt_shell_printf("Bad arguments %s\n", argv[1]);
  905. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  906. }
  907. app_idx = (uint16_t) parms[0];
  908. net_idx = keys_get_bound_key(app_idx);
  909. /* Pack bound NetKey and AppKey into 3 octets */
  910. msg[n] = net_idx;
  911. msg[n + 1] = ((net_idx >> 8) & 0xf) | ((app_idx << 4) & 0xf0);
  912. msg[n + 2] = app_idx >> 4;
  913. n += 3;
  914. if (!config_send(msg, n, OP_APPKEY_DELETE))
  915. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  916. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  917. }
  918. static void cmd_appkey_get(int argc, char *argv[])
  919. {
  920. uint16_t n;
  921. uint8_t msg[32];
  922. if (IS_UNASSIGNED(target)) {
  923. bt_shell_printf("Destination not set\n");
  924. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  925. }
  926. n = mesh_opcode_set(OP_APPKEY_GET, msg);
  927. if (read_input_parameters(argc, argv) != 1) {
  928. bt_shell_printf("Bad arguments %s\n", argv[1]);
  929. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  930. }
  931. put_le16(parms[0], msg + n);
  932. n += 2;
  933. if (!config_send(msg, n, OP_APPKEY_GET))
  934. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  935. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  936. }
  937. static void cmd_key_add(uint32_t opcode, int argc, char *argv[])
  938. {
  939. uint16_t key_idx;
  940. bool is_appkey, update;
  941. const struct cfg_cmd *cmd;
  942. if (IS_UNASSIGNED(target)) {
  943. bt_shell_printf("Destination not set\n");
  944. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  945. }
  946. if (!send_key_msg) {
  947. bt_shell_printf("Send key callback not set\n");
  948. return;
  949. }
  950. if (read_input_parameters(argc, argv) != 1) {
  951. bt_shell_printf("Bad arguments %s\n", argv[1]);
  952. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  953. }
  954. cmd = get_cmd(opcode);
  955. if (!cmd)
  956. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  957. if (get_req_by_rsp(target, cmd->rsp)) {
  958. bt_shell_printf("Another key command is pending\n");
  959. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  960. }
  961. key_idx = (uint16_t) parms[0];
  962. update = (opcode == OP_NETKEY_UPDATE || opcode == OP_APPKEY_UPDATE);
  963. is_appkey = (opcode == OP_APPKEY_ADD || opcode == OP_APPKEY_UPDATE);
  964. if (!send_key_msg(key_data, target, key_idx, is_appkey, update))
  965. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  966. add_request(opcode);
  967. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  968. }
  969. static void cmd_netkey_add(int argc, char *argv[])
  970. {
  971. cmd_key_add(OP_NETKEY_ADD, argc, argv);
  972. }
  973. static void cmd_netkey_update(int argc, char *argv[])
  974. {
  975. cmd_key_add(OP_NETKEY_UPDATE, argc, argv);
  976. }
  977. static void cmd_appkey_add(int argc, char *argv[])
  978. {
  979. cmd_key_add(OP_APPKEY_ADD, argc, argv);
  980. }
  981. static void cmd_appkey_update(int argc, char *argv[])
  982. {
  983. cmd_key_add(OP_APPKEY_UPDATE, argc, argv);
  984. }
  985. static void cmd_bind(uint32_t opcode, int argc, char *argv[])
  986. {
  987. uint16_t n;
  988. uint8_t msg[32];
  989. uint32_t parm_cnt;
  990. parm_cnt = read_input_parameters(argc, argv);
  991. if (parm_cnt != 3 && parm_cnt != 4) {
  992. bt_shell_printf("Bad arguments\n");
  993. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  994. }
  995. if (!remote_has_composition(target)) {
  996. bt_shell_printf("Node composition is unknown\n");
  997. bt_shell_printf("Call \"get-composition\" first\n");
  998. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  999. }
  1000. n = mesh_opcode_set(opcode, msg);
  1001. put_le16(parms[0], msg + n);
  1002. n += 2;
  1003. put_le16(parms[1], msg + n);
  1004. n += 2;
  1005. n += put_model_id(msg + n, &parms[2], parm_cnt == 4);
  1006. if (!config_send(msg, n, opcode))
  1007. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1008. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1009. }
  1010. static void cmd_add_binding(int argc, char *argv[])
  1011. {
  1012. cmd_bind(OP_MODEL_APP_BIND, argc, argv);
  1013. }
  1014. static void cmd_del_binding(int argc, char *argv[])
  1015. {
  1016. cmd_bind(OP_MODEL_APP_UNBIND, argc, argv);
  1017. }
  1018. static void cmd_beacon_set(int argc, char *argv[])
  1019. {
  1020. uint16_t n;
  1021. uint8_t msg[2 + 1];
  1022. uint32_t parm_cnt;
  1023. n = mesh_opcode_set(OP_CONFIG_BEACON_SET, msg);
  1024. parm_cnt = read_input_parameters(argc, argv);
  1025. if (parm_cnt != 1) {
  1026. bt_shell_printf("bad arguments\n");
  1027. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1028. }
  1029. msg[n++] = parms[0];
  1030. if (!config_send(msg, n, OP_CONFIG_BEACON_SET))
  1031. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1032. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1033. }
  1034. static void cmd_beacon_get(int argc, char *argv[])
  1035. {
  1036. cmd_default(OP_CONFIG_BEACON_GET);
  1037. }
  1038. static void cmd_ident_set(int argc, char *argv[])
  1039. {
  1040. uint16_t n;
  1041. uint8_t msg[2 + 3 + 4];
  1042. uint32_t parm_cnt;
  1043. n = mesh_opcode_set(OP_NODE_IDENTITY_SET, msg);
  1044. parm_cnt = read_input_parameters(argc, argv);
  1045. if (parm_cnt != 2) {
  1046. bt_shell_printf("bad arguments\n");
  1047. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1048. }
  1049. put_le16(parms[0], msg + n);
  1050. n += 2;
  1051. msg[n++] = parms[1];
  1052. if (!config_send(msg, n, OP_NODE_IDENTITY_SET))
  1053. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1054. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1055. }
  1056. static void cmd_ident_get(int argc, char *argv[])
  1057. {
  1058. uint16_t n;
  1059. uint8_t msg[2 + 2 + 4];
  1060. uint32_t parm_cnt;
  1061. n = mesh_opcode_set(OP_NODE_IDENTITY_GET, msg);
  1062. parm_cnt = read_input_parameters(argc, argv);
  1063. if (parm_cnt != 1) {
  1064. bt_shell_printf("bad arguments\n");
  1065. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1066. }
  1067. put_le16(parms[0], msg + n);
  1068. n += 2;
  1069. if (!config_send(msg, n, OP_NODE_IDENTITY_GET))
  1070. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1071. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1072. }
  1073. static void cmd_proxy_set(int argc, char *argv[])
  1074. {
  1075. uint16_t n;
  1076. uint8_t msg[2 + 1];
  1077. uint32_t parm_cnt;
  1078. n = mesh_opcode_set(OP_CONFIG_PROXY_SET, msg);
  1079. parm_cnt = read_input_parameters(argc, argv);
  1080. if (parm_cnt != 1) {
  1081. bt_shell_printf("bad arguments");
  1082. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1083. }
  1084. msg[n++] = parms[0];
  1085. if (!config_send(msg, n, OP_CONFIG_PROXY_SET))
  1086. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1087. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1088. }
  1089. static void cmd_proxy_get(int argc, char *argv[])
  1090. {
  1091. cmd_default(OP_CONFIG_PROXY_GET);
  1092. }
  1093. static void cmd_relay_set(int argc, char *argv[])
  1094. {
  1095. uint16_t n;
  1096. uint8_t msg[2 + 2 + 4];
  1097. uint32_t parm_cnt;
  1098. n = mesh_opcode_set(OP_CONFIG_RELAY_SET, msg);
  1099. parm_cnt = read_input_parameters(argc, argv);
  1100. if (parm_cnt != 3) {
  1101. bt_shell_printf("bad arguments\n");
  1102. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1103. }
  1104. msg[n++] = parms[0];
  1105. msg[n++] = parms[1] | (parms[2] << 3);
  1106. if (!config_send(msg, n, OP_CONFIG_RELAY_SET))
  1107. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1108. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1109. }
  1110. static void cmd_relay_get(int argc, char *argv[])
  1111. {
  1112. cmd_default(OP_CONFIG_RELAY_GET);
  1113. }
  1114. static void cmd_ttl_set(int argc, char *argv[])
  1115. {
  1116. uint16_t n;
  1117. uint8_t msg[32];
  1118. uint32_t parm_cnt;
  1119. parm_cnt = read_input_parameters(argc, argv);
  1120. if (!parm_cnt || parms[0] > TTL_MASK) {
  1121. bt_shell_printf("Bad TTL value\n");
  1122. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1123. }
  1124. n = mesh_opcode_set(OP_CONFIG_DEFAULT_TTL_SET, msg);
  1125. msg[n++] = parms[0];
  1126. if (!config_send(msg, n, OP_CONFIG_DEFAULT_TTL_SET))
  1127. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1128. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1129. }
  1130. static void cmd_pub_set(int argc, char *argv[])
  1131. {
  1132. uint16_t n;
  1133. uint8_t msg[48];
  1134. uint32_t parm_cnt;
  1135. struct mesh_group *grp;
  1136. uint32_t opcode;
  1137. uint16_t pub_addr;
  1138. parm_cnt = read_input_parameters(argc, argv);
  1139. if (parm_cnt != 6 && parm_cnt != 7) {
  1140. bt_shell_printf("Bad arguments\n");
  1141. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1142. }
  1143. if (parms[1] > ALL_NODES_ADDRESS) {
  1144. bt_shell_printf("Bad publication address %x\n", parms[1]);
  1145. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1146. }
  1147. if (!remote_has_composition(target)) {
  1148. bt_shell_printf("Node composition is unknown\n");
  1149. bt_shell_printf("Call \"get-composition\" first\n");
  1150. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1151. }
  1152. pub_addr = parms[1];
  1153. grp = l_queue_find(groups, match_group_addr, L_UINT_TO_PTR(pub_addr));
  1154. if (!grp)
  1155. grp = add_group(pub_addr);
  1156. if (!grp && IS_VIRTUAL(pub_addr)) {
  1157. print_virtual_not_found(pub_addr);
  1158. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1159. }
  1160. opcode = (!IS_VIRTUAL(pub_addr)) ? OP_CONFIG_MODEL_PUB_SET :
  1161. OP_CONFIG_MODEL_PUB_VIRT_SET;
  1162. n = mesh_opcode_set(opcode, msg);
  1163. put_le16(parms[0], msg + n);
  1164. n += 2;
  1165. /* Publish address */
  1166. if (!IS_VIRTUAL(pub_addr)) {
  1167. put_le16(pub_addr, msg + n);
  1168. n += 2;
  1169. } else {
  1170. memcpy(msg + n, grp->label, 16);
  1171. n += 16;
  1172. }
  1173. /* AppKey index + credential (set to 0) */
  1174. put_le16(parms[2], msg + n);
  1175. n += 2;
  1176. /* TTL */
  1177. msg[n++] = DEFAULT_TTL;
  1178. /* Publish period step count and step resolution */
  1179. msg[n++] = parms[3];
  1180. /* Publish retransmit count & interval steps */
  1181. msg[n++] = parms[4];
  1182. /* Model Id */
  1183. n += put_model_id(msg + n, &parms[5], parm_cnt == 7);
  1184. if (!config_send(msg, n, opcode))
  1185. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1186. bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1187. }
  1188. static void cmd_pub_get(int argc, char *argv[])
  1189. {
  1190. uint16_t n;
  1191. uint8_t msg[32];
  1192. uint32_t parm_cnt;
  1193. n = mesh_opcode_set(OP_CONFIG_MODEL_PUB_GET, msg);
  1194. parm_cnt = read_input_parameters(argc, argv);
  1195. if (parm_cnt != 2 && parm_cnt != 3) {
  1196. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1197. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1198. }
  1199. /* Element Address */
  1200. put_le16(parms[0], msg + n);
  1201. n += 2;
  1202. /* Model Id */
  1203. n += put_model_id(msg + n, &parms[1], parm_cnt == 3);
  1204. if (!config_send(msg, n, OP_CONFIG_MODEL_PUB_GET))
  1205. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1206. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1207. }
  1208. static void subscription_cmd(int argc, char *argv[], uint32_t opcode)
  1209. {
  1210. uint16_t n;
  1211. uint8_t msg[32];
  1212. uint32_t parm_cnt;
  1213. struct mesh_group *grp;
  1214. uint16_t sub_addr;
  1215. parm_cnt = read_input_parameters(argc, argv);
  1216. if (parm_cnt != 3 && parm_cnt != 4) {
  1217. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1218. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1219. }
  1220. if ((!IS_GROUP(parms[1]) || IS_ALL_NODES(parms[1])) &&
  1221. !IS_VIRTUAL(parms[1])) {
  1222. bt_shell_printf("Bad subscription address %x\n", parms[1]);
  1223. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1224. }
  1225. if (!remote_has_composition(target)) {
  1226. bt_shell_printf("Node composition is unknown\n");
  1227. bt_shell_printf("Call \"get-composition\" first\n");
  1228. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1229. }
  1230. sub_addr = parms[1];
  1231. grp = l_queue_find(groups, match_group_addr, L_UINT_TO_PTR(sub_addr));
  1232. if (!grp && IS_VIRTUAL(sub_addr)) {
  1233. print_virtual_not_found(sub_addr);
  1234. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1235. }
  1236. if (!grp && opcode != OP_CONFIG_MODEL_SUB_DELETE)
  1237. grp = add_group(sub_addr);
  1238. if (IS_VIRTUAL(sub_addr)) {
  1239. if (opcode == OP_CONFIG_MODEL_SUB_ADD)
  1240. opcode = OP_CONFIG_MODEL_SUB_VIRT_ADD;
  1241. else if (opcode == OP_CONFIG_MODEL_SUB_DELETE)
  1242. opcode = OP_CONFIG_MODEL_SUB_VIRT_DELETE;
  1243. else if (opcode == OP_CONFIG_MODEL_SUB_OVERWRITE)
  1244. opcode = OP_CONFIG_MODEL_SUB_VIRT_OVERWRITE;
  1245. }
  1246. n = mesh_opcode_set(opcode, msg);
  1247. /* Element Address */
  1248. put_le16(parms[0], msg + n);
  1249. n += 2;
  1250. /* Subscription Address */
  1251. if (!IS_VIRTUAL(sub_addr)) {
  1252. put_le16(sub_addr, msg + n);
  1253. n += 2;
  1254. } else {
  1255. memcpy(msg + n, grp->label, 16);
  1256. n += 16;
  1257. }
  1258. /* Model ID */
  1259. n += put_model_id(msg + n, &parms[2], parm_cnt == 4);
  1260. if (!config_send(msg, n, opcode))
  1261. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1262. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1263. }
  1264. static void cmd_sub_add(int argc, char *argv[])
  1265. {
  1266. subscription_cmd(argc, argv, OP_CONFIG_MODEL_SUB_ADD);
  1267. }
  1268. static void cmd_sub_del(int argc, char *argv[])
  1269. {
  1270. subscription_cmd(argc, argv, OP_CONFIG_MODEL_SUB_DELETE);
  1271. }
  1272. static void cmd_sub_ovwrt(int argc, char *argv[])
  1273. {
  1274. subscription_cmd(argc, argv, OP_CONFIG_MODEL_SUB_OVERWRITE);
  1275. }
  1276. static void cmd_sub_del_all(int argc, char *argv[])
  1277. {
  1278. uint16_t n;
  1279. uint8_t msg[32];
  1280. uint32_t parm_cnt;
  1281. n = mesh_opcode_set(OP_CONFIG_MODEL_SUB_DELETE_ALL, msg);
  1282. parm_cnt = read_input_parameters(argc, argv);
  1283. if (parm_cnt != 2 && parm_cnt != 3) {
  1284. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1285. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1286. }
  1287. /* Element Address */
  1288. put_le16(parms[0], msg + n);
  1289. n += 2;
  1290. /* Model ID */
  1291. n += put_model_id(msg + n, &parms[1], parm_cnt == 3);
  1292. if (!config_send(msg, n, OP_CONFIG_MODEL_SUB_DELETE_ALL))
  1293. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1294. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1295. }
  1296. static void cmd_sub_get(int argc, char *argv[])
  1297. {
  1298. uint16_t n;
  1299. uint8_t msg[32];
  1300. uint32_t parm_cnt;
  1301. bool vendor;
  1302. uint32_t opcode;
  1303. parm_cnt = read_input_parameters(argc, argv);
  1304. if (parm_cnt != 2 && parm_cnt != 3) {
  1305. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1306. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1307. }
  1308. vendor = (parm_cnt == 3);
  1309. opcode = !vendor ? OP_CONFIG_MODEL_SUB_GET :
  1310. OP_CONFIG_VEND_MODEL_SUB_GET;
  1311. n = mesh_opcode_set(opcode, msg);
  1312. /* Element Address */
  1313. put_le16(parms[0], msg + n);
  1314. n += 2;
  1315. /* Model ID */
  1316. n += put_model_id(msg + n, &parms[1], vendor);
  1317. if (!config_send(msg, n, opcode))
  1318. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1319. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1320. }
  1321. static void cmd_mod_appidx_get(int argc, char *argv[])
  1322. {
  1323. uint16_t n;
  1324. uint8_t msg[32];
  1325. uint32_t parm_cnt;
  1326. bool vendor;
  1327. uint32_t opcode;
  1328. parm_cnt = read_input_parameters(argc, argv);
  1329. if (parm_cnt != 2 && parm_cnt != 3) {
  1330. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1331. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1332. }
  1333. vendor = (parm_cnt == 3);
  1334. opcode = !vendor ? OP_MODEL_APP_GET : OP_VEND_MODEL_APP_GET;
  1335. n = mesh_opcode_set(opcode, msg);
  1336. /* Element Address */
  1337. put_le16(parms[0], msg + n);
  1338. n += 2;
  1339. /* Model ID */
  1340. n += put_model_id(msg + n, &parms[1], vendor);
  1341. if (!config_send(msg, n, opcode))
  1342. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1343. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1344. }
  1345. static void cmd_hb_pub_set(int argc, char *argv[])
  1346. {
  1347. uint16_t n;
  1348. uint8_t msg[32];
  1349. uint32_t parm_cnt;
  1350. n = mesh_opcode_set(OP_CONFIG_HEARTBEAT_PUB_SET, msg);
  1351. if (!l_queue_find(groups, match_group_addr, L_UINT_TO_PTR(parms[1])))
  1352. add_group(parms[1]);
  1353. parm_cnt = read_input_parameters(argc, argv);
  1354. if (parm_cnt != 6) {
  1355. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1356. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1357. }
  1358. /* Per Mesh Profile 4.3.2.62 */
  1359. /* Publish address */
  1360. put_le16(parms[0], msg + n);
  1361. n += 2;
  1362. /* Count Log */
  1363. msg[n++] = parms[1];
  1364. /* Period Log */
  1365. msg[n++] = parms[2];
  1366. /* Heartbeat TTL */
  1367. msg[n++] = parms[3];
  1368. /* Features */
  1369. put_le16(parms[4], msg + n);
  1370. n += 2;
  1371. /* NetKey Index */
  1372. put_le16(parms[5], msg + n);
  1373. n += 2;
  1374. if (!config_send(msg, n, OP_CONFIG_HEARTBEAT_PUB_SET))
  1375. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1376. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1377. }
  1378. static void cmd_hb_pub_get(int argc, char *argv[])
  1379. {
  1380. cmd_default(OP_CONFIG_HEARTBEAT_PUB_GET);
  1381. }
  1382. static void cmd_hb_sub_set(int argc, char *argv[])
  1383. {
  1384. uint16_t n;
  1385. uint8_t msg[32];
  1386. uint32_t parm_cnt;
  1387. if (IS_UNASSIGNED(target)) {
  1388. bt_shell_printf("Destination not set\n");
  1389. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1390. }
  1391. n = mesh_opcode_set(OP_CONFIG_HEARTBEAT_SUB_SET, msg);
  1392. parm_cnt = read_input_parameters(argc, argv);
  1393. if (parm_cnt != 3) {
  1394. bt_shell_printf("Bad arguments: %s\n", argv[1]);
  1395. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1396. }
  1397. if (!l_queue_find(groups, match_group_addr, L_UINT_TO_PTR(parms[1])))
  1398. add_group(parms[1]);
  1399. /* Per Mesh Profile 4.3.2.65 */
  1400. /* Source address */
  1401. put_le16(parms[0], msg + n);
  1402. n += 2;
  1403. /* Destination address */
  1404. put_le16(parms[1], msg + n);
  1405. n += 2;
  1406. /* Period log */
  1407. msg[n++] = parms[2];
  1408. if (!config_send(msg, n, OP_CONFIG_HEARTBEAT_SUB_SET))
  1409. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1410. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1411. }
  1412. static void cmd_hb_sub_get(int argc, char *argv[])
  1413. {
  1414. cmd_default(OP_CONFIG_HEARTBEAT_SUB_GET);
  1415. }
  1416. static void cmd_ttl_get(int argc, char *argv[])
  1417. {
  1418. cmd_default(OP_CONFIG_DEFAULT_TTL_GET);
  1419. }
  1420. static void cmd_network_transmit_get(int argc, char *argv[])
  1421. {
  1422. cmd_default(OP_CONFIG_NETWORK_TRANSMIT_GET);
  1423. }
  1424. static void cmd_network_transmit_set(int argc, char *argv[])
  1425. {
  1426. uint16_t n;
  1427. uint8_t msg[2 + 1];
  1428. uint32_t parm_cnt;
  1429. n = mesh_opcode_set(OP_CONFIG_NETWORK_TRANSMIT_SET, msg);
  1430. parm_cnt = read_input_parameters(argc, argv);
  1431. if (parm_cnt != 2) {
  1432. bt_shell_printf("bad arguments\n");
  1433. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1434. }
  1435. msg[n++] = parms[0] | (parms[1] << 3);
  1436. if (!config_send(msg, n, OP_CONFIG_NETWORK_TRANSMIT_SET))
  1437. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1438. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1439. }
  1440. static void cmd_friend_set(int argc, char *argv[])
  1441. {
  1442. uint16_t n;
  1443. uint8_t msg[2 + 1];
  1444. uint32_t parm_cnt;
  1445. n = mesh_opcode_set(OP_CONFIG_FRIEND_SET, msg);
  1446. parm_cnt = read_input_parameters(argc, argv);
  1447. if (parm_cnt != 1) {
  1448. bt_shell_printf("bad arguments");
  1449. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1450. }
  1451. msg[n++] = parms[0];
  1452. if (!config_send(msg, n, OP_CONFIG_FRIEND_SET))
  1453. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1454. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1455. }
  1456. static void cmd_friend_get(int argc, char *argv[])
  1457. {
  1458. cmd_default(OP_CONFIG_FRIEND_GET);
  1459. }
  1460. static void cmd_node_reset(int argc, char *argv[])
  1461. {
  1462. uint16_t n, i;
  1463. uint8_t msg[8];
  1464. struct pending_req *req;
  1465. if (IS_UNASSIGNED(target)) {
  1466. bt_shell_printf("Destination not set\n");
  1467. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1468. }
  1469. /* Cannot remet self */
  1470. if (target == 0x0001) {
  1471. bt_shell_printf("Resetting self not allowed\n");
  1472. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1473. }
  1474. n = mesh_opcode_set(OP_NODE_RESET, msg);
  1475. req = l_new(struct pending_req, 1);
  1476. req->addr = target;
  1477. req->cmd = get_cmd(OP_NODE_RESET);
  1478. /*
  1479. * As a courtesy to the remote node, send the reset command
  1480. * several times. Treat this as a single request with a longer
  1481. * response timeout.
  1482. */
  1483. req->timer = l_timeout_create(rsp_timeout * 2,
  1484. wait_rsp_timeout, req, NULL);
  1485. l_queue_push_tail(requests, req);
  1486. for (i = 0; i < 5; i++)
  1487. send_msg(send_data, target, APP_IDX_DEV_REMOTE, msg, n);
  1488. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1489. }
  1490. static void cmd_netkey_get(int argc, char *argv[])
  1491. {
  1492. cmd_default(OP_NETKEY_GET);
  1493. }
  1494. static void print_group(void *a, void *b)
  1495. {
  1496. struct mesh_group *grp = a;
  1497. char buf[33];
  1498. if (!IS_VIRTUAL(grp->addr)) {
  1499. bt_shell_printf("\tGroup addr: %4.4x\n", grp->addr);
  1500. return;
  1501. }
  1502. hex2str(grp->label, 16, buf, sizeof(buf));
  1503. bt_shell_printf("\tVirtual addr: %4.4x, label: %s\n", grp->addr, buf);
  1504. }
  1505. static void cmd_add_virt(int argc, char *argv[])
  1506. {
  1507. struct mesh_group *grp, *tmp;
  1508. uint8_t max_tries = 3;
  1509. grp = l_new(struct mesh_group, 1);
  1510. retry:
  1511. l_getrandom(grp->label, 16);
  1512. mesh_crypto_virtual_addr(grp->label, &grp->addr);
  1513. /* For simplicity sake, avoid labels that map to the same hash */
  1514. tmp = l_queue_find(groups, match_group_addr, L_UINT_TO_PTR(grp->addr));
  1515. if (!tmp) {
  1516. l_queue_insert(groups, grp, compare_group_addr, NULL);
  1517. print_group(grp, NULL);
  1518. mesh_db_add_group(grp);
  1519. return bt_shell_noninteractive_quit(EXIT_SUCCESS);
  1520. }
  1521. max_tries--;
  1522. if (max_tries)
  1523. goto retry;
  1524. l_free(grp);
  1525. bt_shell_printf("Failed to generate unique label. Try again.");
  1526. bt_shell_noninteractive_quit(EXIT_FAILURE);
  1527. }
  1528. static void cmd_list_groups(int argc, char *argv[])
  1529. {
  1530. l_queue_foreach(groups, print_group, NULL);
  1531. return bt_shell_noninteractive_quit(EXIT_FAILURE);
  1532. }
  1533. static bool tx_setup(model_send_msg_func_t send_func, void *user_data)
  1534. {
  1535. if (!send_func)
  1536. return false;
  1537. send_msg = send_func;
  1538. send_data = user_data;
  1539. return true;
  1540. }
  1541. static const struct bt_shell_menu cfg_menu = {
  1542. .name = "config",
  1543. .desc = "Configuration Model Submenu",
  1544. .entries = {
  1545. {"target", "<unicast>", cmd_dst_set,
  1546. "Set target node to configure"},
  1547. {"timeout", "<seconds>", cmd_timeout_set,
  1548. "Set response timeout (seconds)"},
  1549. {"composition-get", "[page_num]", cmd_composition_get,
  1550. "Get composition data"},
  1551. {"netkey-add", "<net_idx>", cmd_netkey_add,
  1552. "Add NetKey"},
  1553. {"netkey-update", "<net_idx>", cmd_netkey_update,
  1554. "Update NetKey"},
  1555. {"netkey-del", "<net_idx>", cmd_netkey_del,
  1556. "Delete NetKey"},
  1557. {"netkey-get", NULL, cmd_netkey_get,
  1558. "List NetKeys known to the node"},
  1559. {"kr-phase-get", "<net_idx>", cmd_kr_phase_get,
  1560. "Get Key Refresh phase of a NetKey"},
  1561. {"kr-phase-set", "<net_idx> <phase>", cmd_kr_phase_set,
  1562. "Set Key Refresh phase transition of a NetKey"},
  1563. {"appkey-add", "<app_idx>", cmd_appkey_add,
  1564. "Add AppKey"},
  1565. {"appkey-update", "<app_idx>", cmd_appkey_update,
  1566. "Add AppKey"},
  1567. {"appkey-del", "<app_idx>", cmd_appkey_del,
  1568. "Delete AppKey"},
  1569. {"appkey-get", "<net_idx>", cmd_appkey_get,
  1570. "List AppKeys bound to the NetKey"},
  1571. {"bind", "<ele_addr> <app_idx> <model_id> [vendor_id]", cmd_add_binding,
  1572. "Bind AppKey to a model"},
  1573. {"unbind", "<ele_addr> <app_idx> <model_id> [vendor_id]",
  1574. cmd_del_binding,
  1575. "Remove AppKey from a model"},
  1576. {"mod-appidx-get", "<ele_addr> <model_id> [vendor_id]",
  1577. cmd_mod_appidx_get,
  1578. "Get model app_idx"},
  1579. {"ttl-set", "<ttl>", cmd_ttl_set,
  1580. "Set default TTL"},
  1581. {"ttl-get", NULL, cmd_ttl_get,
  1582. "Get default TTL"},
  1583. {"pub-set", "<ele_addr> <pub_addr> <app_idx> <per (step|res)> "
  1584. "<re-xmt (cnt|per)> <model_id> [vendor_id]",
  1585. cmd_pub_set,
  1586. "Set publication"},
  1587. {"pub-get", "<ele_addr> <model_id> [vendor_id]", cmd_pub_get,
  1588. "Get publication"},
  1589. {"proxy-set", "<proxy>", cmd_proxy_set,
  1590. "Set proxy state"},
  1591. {"proxy-get", NULL, cmd_proxy_get,
  1592. "Get proxy state"},
  1593. {"ident-set", "<net_idx> <state>", cmd_ident_set,
  1594. "Set node identity state"},
  1595. {"ident-get", "<net_idx>", cmd_ident_get,
  1596. "Get node identity state"},
  1597. {"beacon-set", "<state>", cmd_beacon_set,
  1598. "Set node identity state"},
  1599. {"beacon-get", NULL, cmd_beacon_get,
  1600. "Get node beacon state"},
  1601. {"relay-set", "<relay> <rexmt count> <rexmt steps>", cmd_relay_set,
  1602. "Set relay"},
  1603. {"relay-get", NULL, cmd_relay_get,
  1604. "Get relay"},
  1605. {"friend-set", "<state>", cmd_friend_set,
  1606. "Set friend state"},
  1607. {"friend-get", NULL, cmd_friend_get,
  1608. "Get friend state"},
  1609. {"network-transmit-get", NULL, cmd_network_transmit_get,
  1610. "Get network transmit state"},
  1611. {"network-transmit-set", "<count> <steps>", cmd_network_transmit_set,
  1612. "Set network transmit state"},
  1613. {"hb-pub-set", "<pub_addr> <count> <period> <ttl> <features> <net_idx>",
  1614. cmd_hb_pub_set,
  1615. "Set heartbeat publish"},
  1616. {"hb-pub-get", NULL, cmd_hb_pub_get,
  1617. "Get heartbeat publish"},
  1618. {"hb-sub-set", "<src_addr> <dst_addr> <period>", cmd_hb_sub_set,
  1619. "Set heartbeat subscribe"},
  1620. {"hb-sub-get", NULL, cmd_hb_sub_get,
  1621. "Get heartbeat subscribe"},
  1622. {"virt-add", NULL, cmd_add_virt, "Generate and add a virtual label"},
  1623. {"group-list", NULL, cmd_list_groups,
  1624. "Display existing group addresses and virtual labels"},
  1625. {"sub-add", "<ele_addr> <sub_addr> <model_id> [vendor]",
  1626. cmd_sub_add, "Add subscription"},
  1627. {"sub-del", "<ele_addr> <sub_addr> <model_id> [vendor]",
  1628. cmd_sub_del, "Delete subscription"},
  1629. {"sub-wrt", "<ele_addr> <sub_addr> <model_id> [vendor]",
  1630. cmd_sub_ovwrt, "Overwrite subscription"},
  1631. {"sub-del-all", "<ele_addr> <model_id> [vendor]", cmd_sub_del_all,
  1632. "Delete subscription"},
  1633. {"sub-get", "<ele_addr> <model_id> [vendor]", cmd_sub_get,
  1634. "Get subscription"},
  1635. {"node-reset", NULL, cmd_node_reset,
  1636. "Reset a node and remove it from network"},
  1637. {} },
  1638. };
  1639. static struct model_info cli_info = {
  1640. .ops = {
  1641. .set_send_func = tx_setup,
  1642. .set_pub_func = NULL,
  1643. .recv = msg_recvd,
  1644. .bind = NULL,
  1645. .pub = NULL
  1646. },
  1647. .mod_id = CONFIG_CLIENT_MODEL_ID,
  1648. .vendor_id = VENDOR_ID_INVALID
  1649. };
  1650. struct model_info *cfgcli_init(key_send_func_t key_send,
  1651. delete_remote_func_t del_node, void *user_data)
  1652. {
  1653. if (!key_send)
  1654. return NULL;
  1655. send_key_msg = key_send;
  1656. key_data = user_data;
  1657. mgr_del_remote = del_node;
  1658. requests = l_queue_new();
  1659. groups = mesh_db_load_groups();
  1660. bt_shell_add_submenu(&cfg_menu);
  1661. return &cli_info;
  1662. }
  1663. void cfgcli_cleanup(void)
  1664. {
  1665. l_queue_destroy(requests, free_request);
  1666. l_queue_destroy(groups, l_free);
  1667. }