1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
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
25 #include <private-lib-core.h>
26
27 static const lws_struct_map_t lsm_wifi_creds[] = {
28 LSM_CARRAY (lws_wifi_creds_t, ssid, "ssid"),
29 LSM_CARRAY (lws_wifi_creds_t, passphrase, "passphrase"),
30 LSM_UNSIGNED (lws_wifi_creds_t, alg, "alg"),
31 LSM_STRING_PTR (lws_wifi_creds_t, bssid, "bssid"),
32 };
33
34 static const lws_struct_map_t lsm_netdev_credentials[] = {
35 LSM_LIST (lws_netdevs_t, owner_creds, lws_wifi_creds_t, list,
36 NULL, lsm_wifi_creds, "credentials"),
37 };
38
39 static const lws_struct_map_t lsm_netdev_schema[] = {
40 LSM_SCHEMA (lws_netdevs_t, NULL, lsm_netdev_credentials,
41 "lws-netdev-creds"),
42 };
43
44
45 //LSM_CHILD_PTR (lws_netdev_instance_wifi_t, ap_cred, lws_wifi_creds_t,
46 // NULL, lsm_wifi_creds, "ap_cred"),
47 //LSM_STRING_PTR (lws_netdev_instance_wifi_t, ap_ip, "ap_ip"),
48
49 int
lws_netdev_credentials_settings_set(lws_netdevs_t * nds)50 lws_netdev_credentials_settings_set(lws_netdevs_t *nds)
51 {
52 lws_struct_serialize_t *js;
53 size_t w = 0, max = 2048;
54 int n, r = 1;
55 uint8_t *buf;
56
57 buf = lws_malloc(max, __func__); /* length should be computed */
58
59 js = lws_struct_json_serialize_create(lsm_netdev_schema,
60 LWS_ARRAY_SIZE(lsm_netdev_schema), 0, nds);
61 if (!js)
62 goto bail;
63
64 n = lws_struct_json_serialize(js, buf, max, &w);
65 lws_struct_json_serialize_destroy(&js);
66 if (n != LSJS_RESULT_FINISH)
67 goto bail;
68
69 lwsl_notice("%s: setting %s\n", __func__, buf);
70
71 if (!lws_settings_plat_set(nds->si, "netdev.creds", buf, w))
72 r = 0;
73
74 bail:
75 if (r)
76 lwsl_err("%s: failed\n", __func__);
77 lws_free(buf);
78
79 return r;
80 }
81
82 int
lws_netdev_credentials_settings_get(lws_netdevs_t * nds)83 lws_netdev_credentials_settings_get(lws_netdevs_t *nds)
84 {
85 struct lejp_ctx ctx;
86 lws_struct_args_t a;
87 size_t l = 0;
88 uint8_t *buf;
89 int m;
90
91 memset(&a, 0, sizeof(a));
92
93 if (lws_settings_plat_get(nds->si, "netdev.creds", NULL, &l)) {
94 lwsl_notice("%s: not in settings\n", __func__);
95 return 1;
96 }
97
98 buf = lws_malloc(l, __func__);
99 if (!buf)
100 return 1;
101
102 if (lws_settings_plat_get(nds->si, "netdev.creds", buf, &l)) {
103 lwsl_err("%s: unexpected settings get fail\n", __func__);
104 goto bail;
105 }
106
107 a.map_st[0] = lsm_netdev_schema;
108 a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_netdev_schema);
109 a.ac_block_size = 512;
110
111 lws_struct_json_init_parse(&ctx, NULL, &a);
112 m = lejp_parse(&ctx, (uint8_t *)buf, l);
113 lws_free(buf);
114 if (m < 0 || !a.dest) {
115 lwsl_notice("%s: JSON decode failed '%s'\n",
116 __func__, lejp_error_to_string(m));
117 goto bail1;
118 }
119
120 /*
121 * Forcibly set the state of the nds creds owner to the synthesized
122 * one in the ac, and keep the ac for as long as we keep the creds out
123 */
124 nds->owner_creds = ((lws_netdevs_t *)a.dest)->owner_creds;
125 nds->ac_creds = a.ac;
126
127 return 0;
128
129 bail:
130 lws_free(buf);
131 bail1:
132 lwsac_free(&a.ac);
133
134 return 1;
135 }
136
137 lws_wifi_creds_t *
lws_netdev_credentials_find(lws_netdevs_t * netdevs,const char * ssid,const uint8_t * bssid)138 lws_netdev_credentials_find(lws_netdevs_t *netdevs, const char *ssid,
139 const uint8_t *bssid)
140 {
141 lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(
142 &netdevs->owner_creds)) {
143 lws_wifi_creds_t *w = lws_container_of(p, lws_wifi_creds_t, list);
144
145 if (!strcmp(ssid, (const char *)&w[1]) &&
146 !memcmp(bssid, w->bssid, 6))
147 return w;
148
149 } lws_end_foreach_dll(p);
150
151 return NULL;
152 }
153
154 lws_netdev_instance_t *
lws_netdev_find(lws_netdevs_t * netdevs,const char * ifname)155 lws_netdev_find(lws_netdevs_t *netdevs, const char *ifname)
156 {
157 lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(
158 &netdevs->owner)) {
159 lws_netdev_instance_t *ni = lws_container_of(p,
160 lws_netdev_instance_t, list);
161
162 if (!strcmp(ifname, ni->name))
163 return ni;
164
165 } lws_end_foreach_dll(p);
166
167 return NULL;
168 }
169
170 /*
171 * Context forwards NETWORK related smd here, in lws thread context
172 */
173
174 int
lws_netdev_smd_cb(void * opaque,lws_smd_class_t _class,lws_usec_t timestamp,void * buf,size_t len)175 lws_netdev_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,
176 void *buf, size_t len)
177 {
178 struct lws_context *ctx = (struct lws_context *)opaque;
179 const char *iface;
180 char setname[16];
181 size_t al = 0;
182
183 /* deal with anything from whole-network perspective */
184
185 /* pass through netdev-specific messages to correct platform handler */
186
187 iface = lws_json_simple_find(buf, len, "\"if\":", &al);
188 if (!iface)
189 return 0;
190
191 lws_start_foreach_dll(struct lws_dll2 *, p, lws_dll2_get_head(
192 &ctx->netdevs.owner)) {
193 lws_netdev_instance_t *ni = lws_container_of(
194 p, lws_netdev_instance_t, list);
195
196 if (!strncmp(ni->name, iface, al)) {
197
198 /*
199 * IP assignment on our netif? We can deal with marking
200 * the last successful association generically...
201 */
202
203 if (ni->type == LWSNDTYP_WIFI &&
204 !lws_json_simple_strcmp(buf, len, "\"type\":",
205 "ipacq")) {
206 const char *ev = lws_json_simple_find(buf, len,
207 "\"ipv4\":", &al);
208 lws_netdev_instance_wifi_t *wnd =
209 (lws_netdev_instance_wifi_t *)ni;
210
211 if (!ev)
212 return 0;
213
214 lws_snprintf(setname, sizeof(setname),
215 "netdev.last.%s", iface);
216
217 lws_settings_plat_printf(ctx->netdevs.si,
218 setname, "{\"ssid\":\"%s\",\"bssid\":"
219 "\"%02X%02X%02X%02X%02X%02X\"}",
220 wnd->current_attempt_ssid,
221 wnd->current_attempt_bssid[0],
222 wnd->current_attempt_bssid[1],
223 wnd->current_attempt_bssid[2],
224 wnd->current_attempt_bssid[3],
225 wnd->current_attempt_bssid[4],
226 wnd->current_attempt_bssid[5]);
227 }
228
229 /*
230 * Pass it through to related netdev instance for
231 * private actions
232 */
233
234 return ni->ops->event(ni, timestamp, buf, len);
235 }
236
237 } lws_end_foreach_dll(p);
238
239 return 0;
240 }
241
242 /*
243 * This is the generic part of the netdev instance initialization that's always
244 * the same, regardless of the netdev type
245 */
246
247 void
lws_netdev_instance_create(lws_netdev_instance_t * ni,struct lws_context * ctx,const lws_netdev_ops_t * ops,const char * name,void * platinfo)248 lws_netdev_instance_create(lws_netdev_instance_t *ni, struct lws_context *ctx,
249 const lws_netdev_ops_t *ops, const char *name,
250 void *platinfo)
251 {
252 ni->ops = ops;
253 ni->name = name;
254 ni->platinfo = platinfo;
255
256 /* add us to the list of active netdevs */
257
258 lws_dll2_add_tail(&ni->list, &ctx->netdevs.owner);
259 }
260
261 void
lws_netdev_instance_remove_destroy(struct lws_netdev_instance * ni)262 lws_netdev_instance_remove_destroy(struct lws_netdev_instance *ni)
263 {
264 lws_dll2_remove(&ni->list);
265 lws_free(ni);
266 }
267
268 lws_netdevs_t *
lws_netdevs_from_ctx(struct lws_context * ctx)269 lws_netdevs_from_ctx(struct lws_context *ctx)
270 {
271 return &ctx->netdevs;
272 }
273