• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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