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