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  * This provides a clean way to interface lws user code to be able to
25  * work unchanged on different systems for fetching common system information,
26  * and performing common system operations like reboot.
27  */
28 
29 /*
30  * Types of system blob that can be set and retreived
31  */
32 
33 typedef enum {
34 	LWS_SYSBLOB_TYPE_AUTH,
35 	LWS_SYSBLOB_TYPE_CLIENT_CERT_DER = LWS_SYSBLOB_TYPE_AUTH + 2,
36 	LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
37 	LWS_SYSBLOB_TYPE_DEVICE_SERIAL,
38 	LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION,
39 	LWS_SYSBLOB_TYPE_DEVICE_TYPE,
40 	LWS_SYSBLOB_TYPE_NTP_SERVER,
41 
42 	LWS_SYSBLOB_TYPE_COUNT /* ... always last */
43 } lws_system_blob_item_t;
44 
45 /* opaque generic blob whose content may be on-the-heap or pointed-to
46  * directly case by case.  When it's on the heap, it can be produced by
47  * appending (it's a buflist underneath).  Either way, it can be consumed by
48  * copying out a given length from a given offset.
49  */
50 
51 typedef struct lws_system_blob lws_system_blob_t;
52 
53 LWS_EXTERN LWS_VISIBLE void
54 lws_system_blob_direct_set(lws_system_blob_t *b, const uint8_t *ptr, size_t len);
55 
56 LWS_EXTERN LWS_VISIBLE void
57 lws_system_blob_heap_empty(lws_system_blob_t *b);
58 
59 LWS_EXTERN LWS_VISIBLE int
60 lws_system_blob_heap_append(lws_system_blob_t *b, const uint8_t *ptr, size_t len);
61 
62 LWS_EXTERN LWS_VISIBLE size_t
63 lws_system_blob_get_size(lws_system_blob_t *b);
64 
65 /* return 0 and sets *ptr to point to blob data if possible, nonzero = fail */
66 LWS_EXTERN LWS_VISIBLE int
67 lws_system_blob_get_single_ptr(lws_system_blob_t *b, const uint8_t **ptr);
68 
69 LWS_EXTERN LWS_VISIBLE int
70 lws_system_blob_get(lws_system_blob_t *b, uint8_t *ptr, size_t *len, size_t ofs);
71 
72 LWS_EXTERN LWS_VISIBLE void
73 lws_system_blob_destroy(lws_system_blob_t *b);
74 
75 /*
76  * Get the opaque blob for index idx of various system blobs.  Returns 0 if
77  * *b was set otherwise nonzero means out of range
78  */
79 
80 LWS_EXTERN LWS_VISIBLE lws_system_blob_t *
81 lws_system_get_blob(struct lws_context *context, lws_system_blob_item_t type,
82                     int idx);
83 
84 /*
85  * Lws view of system state... normal operation from user code perspective is
86  * dependent on implicit (eg, knowing the date for cert validation) and
87  * explicit dependencies.
88  *
89  * Bit of lws and user code can register notification handlers that can enforce
90  * dependent operations before state transitions can complete.
91  */
92 
93 typedef enum { /* keep system_state_names[] in sync in context.c */
94 	LWS_SYSTATE_UNKNOWN,
95 
96 	LWS_SYSTATE_CONTEXT_CREATED,	 /* context was just created */
97 	LWS_SYSTATE_INITIALIZED,	 /* protocols initialized.  Lws itself
98 					  * can operate normally */
99 	LWS_SYSTATE_IFACE_COLDPLUG,	 /* existing net ifaces iterated */
100 	LWS_SYSTATE_DHCP,		 /* at least one net iface configured */
101 	LWS_SYSTATE_TIME_VALID,		 /* ntpclient ran, or hw time valid...
102 					  * tls cannot work until we reach here
103 					  */
104 	LWS_SYSTATE_POLICY_VALID,	 /* user code knows how to operate... */
105 	LWS_SYSTATE_REGISTERED,		 /* device has an identity... */
106 	LWS_SYSTATE_AUTH1,		 /* identity used for main auth token */
107 	LWS_SYSTATE_AUTH2,		 /* identity used for optional auth */
108 
109 	LWS_SYSTATE_OPERATIONAL,	 /* user code can operate normally */
110 
111 	LWS_SYSTATE_POLICY_INVALID,	 /* user code is changing its policies
112 					  * drop everything done with old
113 					  * policy, switch to new then enter
114 					  * LWS_SYSTATE_POLICY_VALID */
115 } lws_system_states_t;
116 
117 
118 typedef void (*lws_attach_cb_t)(struct lws_context *context, int tsi, void *opaque);
119 struct lws_attach_item;
120 
121 typedef struct lws_system_ops {
122 	int (*reboot)(void);
123 	int (*set_clock)(lws_usec_t us);
124 	int (*attach)(struct lws_context *context, int tsi, lws_attach_cb_t cb,
125 		      lws_system_states_t state, void *opaque,
126 		      struct lws_attach_item **get);
127 	/**< if \p get is NULL, add an attach callback request to the pt for
128 	 * \p cb with arg \p opaque, that should be called when we're at or past
129 	 * system state \p state.
130 	 *
131 	 * If \p get is non-NULL, look for the first listed item on the pt whose
132 	 * state situation is ready, and set *get to point to it.  If no items,
133 	 * or none where the system state is right, set *get to NULL.
134 	 *
135 	 * It's done like this so (*attach) can perform system-specific
136 	 * locking outside of lws core, for both getting and adding items the
137 	 * same so it is thread-safe.  A non-threadsafe helper
138 	 * __lws_system_attach() is provided to do the actual work inside the
139 	 * system-specific locking.
140 	 */
141 } lws_system_ops_t;
142 
143 /**
144  * lws_system_get_state_manager() - return the state mgr object for system state
145  *
146  * \param context: the lws_context
147  *
148  * The returned pointer can be used with the lws_state_ apis
149  */
150 
151 LWS_EXTERN LWS_VISIBLE lws_state_manager_t *
152 lws_system_get_state_manager(struct lws_context *context);
153 
154 
155 
156 /* wrappers handle NULL members or no ops struct set at all cleanly */
157 
158 #define LWSSYSGAUTH_HEX (1 << 0)
159 
160 /**
161  * lws_system_get_ops() - get ahold of the system ops struct from the context
162  *
163  * \param context: the lws_context
164  *
165  * Returns the system ops struct.  It may return NULL and if not, anything in
166  * there may be NULL.
167  */
168 LWS_EXTERN LWS_VISIBLE const lws_system_ops_t *
169 lws_system_get_ops(struct lws_context *context);
170 
171 /**
172  * lws_system_context_from_system_mgr() - return context from system state mgr
173  *
174  * \param mgr: pointer to specifically the system state mgr
175  *
176  * Returns the context from the system state mgr.  Helper since the lws_context
177  * is opaque.
178  */
179 LWS_EXTERN LWS_VISIBLE struct lws_context *
180 lws_system_context_from_system_mgr(lws_state_manager_t *mgr);
181 
182 
183 /**
184  * __lws_system_attach() - get and set items on context attach list
185  *
186  * \param context: context to get or set attach items to
187  * \param tsi: thread service index (normally 0)
188  * \param cb: callback to call from context event loop thread
189  * \param state: the lws_system state we have to be in or have passed through
190  * \param opaque: optional pointer to user specific info given to callback
191  * \param get: NULL, or pointer to pointer to take detached tail item on exit
192  *
193  * This allows other threads to enqueue callback requests to happen from a pt's
194  * event loop thread safely.  The callback gets the context pointer and a user
195  * opaque pointer that can be optionally given when the item is added to the
196  * attach list.
197  *
198  * This api is the no-locking core function for getting and setting items on the
199  * pt's attach list.  The lws_system operation (*attach) is the actual
200  * api that user and internal code calls for this feature, it should perform
201  * system-specific locking, call this helper, release the locking and then
202  * return the result.  This api is public only so it can be used in the locked
203  * implementation of (*attach).
204  *
205  * If get is NULL, then the call adds to the head of the pt attach list using
206  * cb, state, and opaque; if get is non-NULL, then *get is set to the first
207  * waiting attached item that meets the state criteria and that item is removed
208  * from the list.
209  *
210  * This is a non-threadsafe helper only designed to be called from
211  * implementations of struct lws_system's (*attach) operation where system-
212  * specific locking has been applied around it, making it threadsafe.
213  */
214 LWS_EXTERN LWS_VISIBLE int
215 __lws_system_attach(struct lws_context *context, int tsi, lws_attach_cb_t cb,
216 		    lws_system_states_t state, void *opaque,
217 		    struct lws_attach_item **get);
218 
219 
220 typedef int (*dhcpc_cb_t)(void *opaque, int af, uint8_t *ip, int ip_len);
221 
222 /**
223  * lws_dhcpc_request() - add a network interface to dhcpc management
224  *
225  * \param c: the lws_context
226  * \param i: the interface name, like "eth0"
227  * \param af: address family
228  * \param cb: the change callback
229  * \param opaque: opaque pointer given to the callback
230  *
231  * Register a network interface as being managed by DHCP.  lws will proceed to
232  * try to acquire an IP.  Requires LWS_WITH_SYS_DHCP_CLIENT at cmake.
233  */
234 int
235 lws_dhcpc_request(struct lws_context *c, const char *i, int af, dhcpc_cb_t cb,
236 		void *opaque);
237 
238 /**
239  * lws_dhcpc_remove() - remove a network interface to dhcpc management
240  *
241  * \param context: the lws_context
242  * \param iface: the interface name, like "eth0"
243  *
244  * Remove handling of the network interface from dhcp.
245  */
246 int
247 lws_dhcpc_remove(struct lws_context *context, const char *iface);
248 
249 /**
250  * lws_dhcpc_status() - has any interface reached BOUND state
251  *
252  * \param context: the lws_context
253  * \param sa46: set to a DNS server from a bound interface, or NULL
254  *
255  * Returns 1 if any network interface managed by dhcpc has reached the BOUND
256  * state (has acquired an IP, gateway and DNS server), otherwise 0.
257  */
258 int
259 lws_dhcpc_status(struct lws_context *context, lws_sockaddr46 *sa46);
260