netdev.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include <private-lib-core.h>
  25. static const lws_struct_map_t lsm_wifi_creds[] = {
  26. LSM_CARRAY (lws_wifi_creds_t, ssid, "ssid"),
  27. LSM_CARRAY (lws_wifi_creds_t, passphrase, "passphrase"),
  28. LSM_UNSIGNED (lws_wifi_creds_t, alg, "alg"),
  29. LSM_STRING_PTR (lws_wifi_creds_t, bssid, "bssid"),
  30. };
  31. static const lws_struct_map_t lsm_netdev_credentials[] = {
  32. LSM_LIST (lws_netdevs_t, owner_creds, lws_wifi_creds_t, list,
  33. NULL, lsm_wifi_creds, "credentials"),
  34. };
  35. static const lws_struct_map_t lsm_netdev_schema[] = {
  36. LSM_SCHEMA (lws_netdevs_t, NULL, lsm_netdev_credentials,
  37. "lws-netdev-creds"),
  38. };
  39. //LSM_CHILD_PTR (lws_netdev_instance_wifi_t, ap_cred, lws_wifi_creds_t,
  40. // NULL, lsm_wifi_creds, "ap_cred"),
  41. //LSM_STRING_PTR (lws_netdev_instance_wifi_t, ap_ip, "ap_ip"),
  42. int
  43. lws_netdev_credentials_settings_set(lws_netdevs_t *nds)
  44. {
  45. lws_struct_serialize_t *js;
  46. size_t w = 0, max = 2048;
  47. int n, r = 1;
  48. uint8_t *buf;
  49. buf = lws_malloc(max, __func__); /* length should be computed */
  50. js = lws_struct_json_serialize_create(lsm_netdev_schema,
  51. LWS_ARRAY_SIZE(lsm_netdev_schema), 0, nds);
  52. if (!js)
  53. goto bail;
  54. n = lws_struct_json_serialize(js, buf, max, &w);
  55. lws_struct_json_serialize_destroy(&js);
  56. if (n != LSJS_RESULT_FINISH)
  57. goto bail;
  58. lwsl_notice("%s: setting %s\n", __func__, buf);
  59. if (!lws_settings_plat_set(nds->si, "netdev.creds", buf, w))
  60. r = 0;
  61. bail:
  62. if (r)
  63. lwsl_err("%s: failed\n", __func__);
  64. lws_free(buf);
  65. return r;
  66. }
  67. int
  68. lws_netdev_credentials_settings_get(lws_netdevs_t *nds)
  69. {
  70. struct lejp_ctx ctx;
  71. lws_struct_args_t a;
  72. size_t l = 0;
  73. uint8_t *buf;
  74. int m;
  75. memset(&a, 0, sizeof(a));
  76. if (lws_settings_plat_get(nds->si, "netdev.creds", NULL, &l)) {
  77. lwsl_notice("%s: not in settings\n", __func__);
  78. return 1;
  79. }
  80. buf = lws_malloc(l, __func__);
  81. if (!buf)
  82. return 1;
  83. if (lws_settings_plat_get(nds->si, "netdev.creds", buf, &l)) {
  84. lwsl_err("%s: unexpected settings get fail\n", __func__);
  85. goto bail;
  86. }
  87. a.map_st[0] = lsm_netdev_schema;
  88. a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_netdev_schema);
  89. a.ac_block_size = 512;
  90. lws_struct_json_init_parse(&ctx, NULL, &a);
  91. m = lejp_parse(&ctx, (uint8_t *)buf, l);
  92. lws_free(buf);
  93. if (m < 0 || !a.dest) {
  94. lwsl_notice("%s: JSON decode failed '%s'\n",
  95. __func__, lejp_error_to_string(m));
  96. goto bail1;
  97. }
  98. /*
  99. * Forcibly set the state of the nds creds owner to the synthesized
  100. * one in the ac, and keep the ac for as long as we keep the creds out
  101. */
  102. nds->owner_creds = ((lws_netdevs_t *)a.dest)->owner_creds;
  103. nds->ac_creds = a.ac;
  104. return 0;
  105. bail:
  106. lws_free(buf);
  107. bail1:
  108. lwsac_free(&a.ac);
  109. return 1;
  110. }
  111. lws_wifi_creds_t *
  112. lws_netdev_credentials_find(lws_netdevs_t *netdevs, const char *ssid,
  113. const uint8_t *bssid)
  114. {
  115. lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(
  116. &netdevs->owner_creds)) {
  117. lws_wifi_creds_t *w = lws_container_of(p, lws_wifi_creds_t, list);
  118. if (!strcmp(ssid, (const char *)&w[1]) &&
  119. !memcmp(bssid, w->bssid, 6))
  120. return w;
  121. } lws_end_foreach_dll(p);
  122. return NULL;
  123. }
  124. lws_netdev_instance_t *
  125. lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname)
  126. {
  127. lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(
  128. &netdevs->owner)) {
  129. lws_netdev_instance_t *ni = lws_container_of(p,
  130. lws_netdev_instance_t, list);
  131. if (!strcmp(ifname, ni->name))
  132. return ni;
  133. } lws_end_foreach_dll(p);
  134. return NULL;
  135. }
  136. /*
  137. * Context forwards NETWORK related smd here, in lws thread context
  138. */
  139. int
  140. lws_netdev_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,
  141. void *buf, size_t len)
  142. {
  143. struct lws_context *ctx = (struct lws_context *)opaque;
  144. const char *iface;
  145. char setname[16];
  146. size_t al = 0;
  147. /* deal with anything from whole-network perspective */
  148. /* pass through netdev-specific messages to correct platform handler */
  149. iface = lws_json_simple_find(buf, len, "\"if\":", &al);
  150. if (!iface)
  151. return 0;
  152. lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(
  153. &ctx->netdevs.owner)) {
  154. lws_netdev_instance_t *ni = lws_container_of(
  155. p, lws_netdev_instance_t, list);
  156. if (!strncmp(ni->name, iface, al)) {
  157. /*
  158. * IP assignment on our netif? We can deal with marking
  159. * the last successful association generically...
  160. */
  161. if (ni->type == LWSNDTYP_WIFI &&
  162. !lws_json_simple_strcmp(buf, len, "\"type\":",
  163. "ipacq")) {
  164. const char *ev = lws_json_simple_find(buf, len,
  165. "\"ipv4\":", &al);
  166. lws_netdev_instance_wifi_t *wnd =
  167. (lws_netdev_instance_wifi_t *)ni;
  168. if (!ev)
  169. return 0;
  170. lws_snprintf(setname, sizeof(setname),
  171. "netdev.last.%s", iface);
  172. lws_settings_plat_printf(ctx->netdevs.si,
  173. setname, "{\"ssid\":\"%s\",\"bssid\":"
  174. "\"%02X%02X%02X%02X%02X%02X\"}",
  175. wnd->current_attempt_ssid,
  176. wnd->current_attempt_bssid[0],
  177. wnd->current_attempt_bssid[1],
  178. wnd->current_attempt_bssid[2],
  179. wnd->current_attempt_bssid[3],
  180. wnd->current_attempt_bssid[4],
  181. wnd->current_attempt_bssid[5]);
  182. }
  183. /*
  184. * Pass it through to related netdev instance for
  185. * private actions
  186. */
  187. return ni->ops->event(ni, timestamp, buf, len);
  188. }
  189. } lws_end_foreach_dll(p);
  190. return 0;
  191. }
  192. /*
  193. * This is the generic part of the netdev instance initialization that's always
  194. * the same, regardless of the netdev type
  195. */
  196. void
  197. lws_netdev_instance_create(lws_netdev_instance_t *ni, struct lws_context *ctx,
  198. const lws_netdev_ops_t *ops, const char *name,
  199. void *platinfo)
  200. {
  201. ni->ops = ops;
  202. ni->name = name;
  203. ni->platinfo = platinfo;
  204. /* add us to the list of active netdevs */
  205. lws_dll2_add_tail(&ni->list, &ctx->netdevs.owner);
  206. }
  207. void
  208. lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni)
  209. {
  210. lws_dll2_remove(&ni->list);
  211. lws_free(ni);
  212. }
  213. lws_netdevs_t *
  214. lws_netdevs_from_ctx(struct lws_context *ctx)
  215. {
  216. return &ctx->netdevs;
  217. }