1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws System Fault Injection
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2019 - 2021 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
28*1c60b9acSAndroid Build Coastguard Worker
29*1c60b9acSAndroid Build Coastguard Worker static lws_fi_priv_t *
lws_fi_lookup(const lws_fi_ctx_t * fic,const char * name)30*1c60b9acSAndroid Build Coastguard Worker lws_fi_lookup(const lws_fi_ctx_t *fic, const char *name)
31*1c60b9acSAndroid Build Coastguard Worker {
32*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, p, fic->fi_owner.head) {
33*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(pv->fi.name, name))
36*1c60b9acSAndroid Build Coastguard Worker return pv;
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(p);
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker return NULL;
41*1c60b9acSAndroid Build Coastguard Worker }
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker int
lws_fi(const lws_fi_ctx_t * fic,const char * name)44*1c60b9acSAndroid Build Coastguard Worker lws_fi(const lws_fi_ctx_t *fic, const char *name)
45*1c60b9acSAndroid Build Coastguard Worker {
46*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv;
47*1c60b9acSAndroid Build Coastguard Worker int n;
48*1c60b9acSAndroid Build Coastguard Worker
49*1c60b9acSAndroid Build Coastguard Worker pv = lws_fi_lookup(fic, name);
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker if (!pv)
52*1c60b9acSAndroid Build Coastguard Worker return 0;
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker switch (pv->fi.type) {
55*1c60b9acSAndroid Build Coastguard Worker case LWSFI_ALWAYS:
56*1c60b9acSAndroid Build Coastguard Worker goto inject;
57*1c60b9acSAndroid Build Coastguard Worker
58*1c60b9acSAndroid Build Coastguard Worker case LWSFI_DETERMINISTIC:
59*1c60b9acSAndroid Build Coastguard Worker pv->fi.times++;
60*1c60b9acSAndroid Build Coastguard Worker if (pv->fi.times >= pv->fi.pre)
61*1c60b9acSAndroid Build Coastguard Worker if (pv->fi.times < pv->fi.pre + pv->fi.count)
62*1c60b9acSAndroid Build Coastguard Worker goto inject;
63*1c60b9acSAndroid Build Coastguard Worker return 0;
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker case LWSFI_PROBABILISTIC:
66*1c60b9acSAndroid Build Coastguard Worker if (lws_xos_percent((lws_xos_t *)&fic->xos, (int)pv->fi.pre))
67*1c60b9acSAndroid Build Coastguard Worker goto inject;
68*1c60b9acSAndroid Build Coastguard Worker return 0;
69*1c60b9acSAndroid Build Coastguard Worker
70*1c60b9acSAndroid Build Coastguard Worker case LWSFI_PATTERN:
71*1c60b9acSAndroid Build Coastguard Worker case LWSFI_PATTERN_ALLOC:
72*1c60b9acSAndroid Build Coastguard Worker n = (int)((pv->fi.times++) % pv->fi.count);
73*1c60b9acSAndroid Build Coastguard Worker if (pv->fi.pattern[n >> 3] & (1 << (n & 7)))
74*1c60b9acSAndroid Build Coastguard Worker goto inject;
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker return 0;
77*1c60b9acSAndroid Build Coastguard Worker
78*1c60b9acSAndroid Build Coastguard Worker default:
79*1c60b9acSAndroid Build Coastguard Worker return 0;
80*1c60b9acSAndroid Build Coastguard Worker }
81*1c60b9acSAndroid Build Coastguard Worker
82*1c60b9acSAndroid Build Coastguard Worker return 0;
83*1c60b9acSAndroid Build Coastguard Worker
84*1c60b9acSAndroid Build Coastguard Worker inject:
85*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: Injecting fault %s->%s\n", __func__,
86*1c60b9acSAndroid Build Coastguard Worker fic->name ? fic->name : "unk", pv->fi.name);
87*1c60b9acSAndroid Build Coastguard Worker
88*1c60b9acSAndroid Build Coastguard Worker return 1;
89*1c60b9acSAndroid Build Coastguard Worker }
90*1c60b9acSAndroid Build Coastguard Worker
91*1c60b9acSAndroid Build Coastguard Worker int
lws_fi_range(const lws_fi_ctx_t * fic,const char * name,uint64_t * result)92*1c60b9acSAndroid Build Coastguard Worker lws_fi_range(const lws_fi_ctx_t *fic, const char *name, uint64_t *result)
93*1c60b9acSAndroid Build Coastguard Worker {
94*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv;
95*1c60b9acSAndroid Build Coastguard Worker uint64_t d;
96*1c60b9acSAndroid Build Coastguard Worker
97*1c60b9acSAndroid Build Coastguard Worker pv = lws_fi_lookup(fic, name);
98*1c60b9acSAndroid Build Coastguard Worker
99*1c60b9acSAndroid Build Coastguard Worker if (!pv)
100*1c60b9acSAndroid Build Coastguard Worker return 1;
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker if (pv->fi.type != LWSFI_RANGE) {
103*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: fault %s is not a 123..456 range\n",
104*1c60b9acSAndroid Build Coastguard Worker __func__, name);
105*1c60b9acSAndroid Build Coastguard Worker return 1;
106*1c60b9acSAndroid Build Coastguard Worker }
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker d = pv->fi.count - pv->fi.pre;
109*1c60b9acSAndroid Build Coastguard Worker
110*1c60b9acSAndroid Build Coastguard Worker *result = pv->fi.pre + (lws_xos((lws_xos_t *)&fic->xos) % d);
111*1c60b9acSAndroid Build Coastguard Worker
112*1c60b9acSAndroid Build Coastguard Worker return 0;
113*1c60b9acSAndroid Build Coastguard Worker }
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_wsi_fi(struct lws * wsi,const char * name)116*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_wsi_fi(struct lws *wsi, const char *name)
117*1c60b9acSAndroid Build Coastguard Worker {
118*1c60b9acSAndroid Build Coastguard Worker return lws_fi(&wsi->fic, name);
119*1c60b9acSAndroid Build Coastguard Worker }
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_context_fi(struct lws_context * ctx,const char * name)122*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_context_fi(struct lws_context *ctx, const char *name)
123*1c60b9acSAndroid Build Coastguard Worker {
124*1c60b9acSAndroid Build Coastguard Worker return lws_fi(&ctx->fic, name);
125*1c60b9acSAndroid Build Coastguard Worker }
126*1c60b9acSAndroid Build Coastguard Worker
127*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
128*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_ss_fi(struct lws_ss_handle * h,const char * name)129*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *name)
130*1c60b9acSAndroid Build Coastguard Worker {
131*1c60b9acSAndroid Build Coastguard Worker return lws_fi(&h->fic, name);
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker
134*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
135*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_sspc_fi(struct lws_sspc_handle * h,const char * name)136*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *name)
137*1c60b9acSAndroid Build Coastguard Worker {
138*1c60b9acSAndroid Build Coastguard Worker return lws_fi(&h->fic, name);
139*1c60b9acSAndroid Build Coastguard Worker }
140*1c60b9acSAndroid Build Coastguard Worker #endif
141*1c60b9acSAndroid Build Coastguard Worker #endif
142*1c60b9acSAndroid Build Coastguard Worker
143*1c60b9acSAndroid Build Coastguard Worker int
lws_fi_add(lws_fi_ctx_t * fic,const lws_fi_t * fi)144*1c60b9acSAndroid Build Coastguard Worker lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi)
145*1c60b9acSAndroid Build Coastguard Worker {
146*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv;
147*1c60b9acSAndroid Build Coastguard Worker size_t n = strlen(fi->name);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker pv = lws_malloc(sizeof(*pv) + n + 1, __func__);
150*1c60b9acSAndroid Build Coastguard Worker if (!pv)
151*1c60b9acSAndroid Build Coastguard Worker return 1;
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker lws_dll2_clear(&pv->list);
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker memcpy(&pv->fi, fi, sizeof(*fi));
156*1c60b9acSAndroid Build Coastguard Worker pv->fi.name = (const char *)&pv[1];
157*1c60b9acSAndroid Build Coastguard Worker memcpy(&pv[1], fi->name, n + 1);
158*1c60b9acSAndroid Build Coastguard Worker
159*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&pv->list, &fic->fi_owner);
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker return 0;
162*1c60b9acSAndroid Build Coastguard Worker }
163*1c60b9acSAndroid Build Coastguard Worker
164*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_remove(lws_fi_ctx_t * fic,const char * name)165*1c60b9acSAndroid Build Coastguard Worker lws_fi_remove(lws_fi_ctx_t *fic, const char *name)
166*1c60b9acSAndroid Build Coastguard Worker {
167*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv = lws_fi_lookup(fic, name);
168*1c60b9acSAndroid Build Coastguard Worker
169*1c60b9acSAndroid Build Coastguard Worker if (!pv)
170*1c60b9acSAndroid Build Coastguard Worker return;
171*1c60b9acSAndroid Build Coastguard Worker
172*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&pv->list);
173*1c60b9acSAndroid Build Coastguard Worker lws_free(pv);
174*1c60b9acSAndroid Build Coastguard Worker }
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_import(lws_fi_ctx_t * fic_dest,const lws_fi_ctx_t * fic_src)177*1c60b9acSAndroid Build Coastguard Worker lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src)
178*1c60b9acSAndroid Build Coastguard Worker {
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker /* inherit the PRNG seed for our context from source guy too */
181*1c60b9acSAndroid Build Coastguard Worker lws_xos_init(&fic_dest->xos, lws_xos((lws_xos_t *)&fic_src->xos));
182*1c60b9acSAndroid Build Coastguard Worker
183*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
184*1c60b9acSAndroid Build Coastguard Worker fic_src->fi_owner.head) {
185*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
186*1c60b9acSAndroid Build Coastguard Worker
187*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&pv->list);
188*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&pv->list, &fic_dest->fi_owner);
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(p, p1);
191*1c60b9acSAndroid Build Coastguard Worker }
192*1c60b9acSAndroid Build Coastguard Worker
193*1c60b9acSAndroid Build Coastguard Worker static void
do_inherit(lws_fi_ctx_t * fic_dest,lws_fi_t * pfi,size_t trim)194*1c60b9acSAndroid Build Coastguard Worker do_inherit(lws_fi_ctx_t *fic_dest, lws_fi_t *pfi, size_t trim)
195*1c60b9acSAndroid Build Coastguard Worker {
196*1c60b9acSAndroid Build Coastguard Worker lws_fi_t fi = *pfi;
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker fi.name += trim;
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s: %s inherited as %s\n", __func__, fic_dest->name,
201*1c60b9acSAndroid Build Coastguard Worker pfi->name, fi.name);
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker if (fi.type == LWSFI_PATTERN_ALLOC) {
204*1c60b9acSAndroid Build Coastguard Worker fi.pattern = lws_malloc((size_t)((fi.count >> 3) + 1), __func__);
205*1c60b9acSAndroid Build Coastguard Worker if (!fi.pattern)
206*1c60b9acSAndroid Build Coastguard Worker return;
207*1c60b9acSAndroid Build Coastguard Worker memcpy((uint8_t *)fi.pattern, pfi->pattern,
208*1c60b9acSAndroid Build Coastguard Worker (size_t)((fi.count >> 3) + 1));
209*1c60b9acSAndroid Build Coastguard Worker }
210*1c60b9acSAndroid Build Coastguard Worker
211*1c60b9acSAndroid Build Coastguard Worker lws_fi_add(fic_dest, &fi);
212*1c60b9acSAndroid Build Coastguard Worker }
213*1c60b9acSAndroid Build Coastguard Worker
214*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_inherit_copy(lws_fi_ctx_t * fic_dest,const lws_fi_ctx_t * fic_src,const char * scope,const char * value)215*1c60b9acSAndroid Build Coastguard Worker lws_fi_inherit_copy(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src,
216*1c60b9acSAndroid Build Coastguard Worker const char *scope, const char *value)
217*1c60b9acSAndroid Build Coastguard Worker {
218*1c60b9acSAndroid Build Coastguard Worker size_t sl = 0, vl = 0;
219*1c60b9acSAndroid Build Coastguard Worker
220*1c60b9acSAndroid Build Coastguard Worker if (scope)
221*1c60b9acSAndroid Build Coastguard Worker sl = strlen(scope);
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker if (value)
224*1c60b9acSAndroid Build Coastguard Worker vl = strlen(value);
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
227*1c60b9acSAndroid Build Coastguard Worker fic_src->fi_owner.head) {
228*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
229*1c60b9acSAndroid Build Coastguard Worker size_t nl = strlen(pv->fi.name);
230*1c60b9acSAndroid Build Coastguard Worker
231*1c60b9acSAndroid Build Coastguard Worker if (!scope)
232*1c60b9acSAndroid Build Coastguard Worker do_inherit(fic_dest, &pv->fi, 0);
233*1c60b9acSAndroid Build Coastguard Worker else
234*1c60b9acSAndroid Build Coastguard Worker if (nl > sl + 2 &&
235*1c60b9acSAndroid Build Coastguard Worker !strncmp(pv->fi.name, scope, sl) &&
236*1c60b9acSAndroid Build Coastguard Worker pv->fi.name[sl] == '/')
237*1c60b9acSAndroid Build Coastguard Worker do_inherit(fic_dest, &pv->fi, sl + 1);
238*1c60b9acSAndroid Build Coastguard Worker else {
239*1c60b9acSAndroid Build Coastguard Worker if (value && nl > sl + vl + 2 &&
240*1c60b9acSAndroid Build Coastguard Worker pv->fi.name[sl] == '=' &&
241*1c60b9acSAndroid Build Coastguard Worker !strncmp(pv->fi.name + sl + 1, value, vl) &&
242*1c60b9acSAndroid Build Coastguard Worker pv->fi.name[sl + 1 + vl] == '/')
243*1c60b9acSAndroid Build Coastguard Worker do_inherit(fic_dest, &pv->fi, sl + vl + 2);
244*1c60b9acSAndroid Build Coastguard Worker }
245*1c60b9acSAndroid Build Coastguard Worker
246*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(p, p1);
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_destroy(const lws_fi_ctx_t * fic)250*1c60b9acSAndroid Build Coastguard Worker lws_fi_destroy(const lws_fi_ctx_t *fic)
251*1c60b9acSAndroid Build Coastguard Worker {
252*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
253*1c60b9acSAndroid Build Coastguard Worker fic->fi_owner.head) {
254*1c60b9acSAndroid Build Coastguard Worker lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
255*1c60b9acSAndroid Build Coastguard Worker
256*1c60b9acSAndroid Build Coastguard Worker if (pv->fi.type == LWSFI_PATTERN_ALLOC && pv->fi.pattern) {
257*1c60b9acSAndroid Build Coastguard Worker lws_free((void *)pv->fi.pattern);
258*1c60b9acSAndroid Build Coastguard Worker pv->fi.pattern = NULL;
259*1c60b9acSAndroid Build Coastguard Worker }
260*1c60b9acSAndroid Build Coastguard Worker
261*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&pv->list);
262*1c60b9acSAndroid Build Coastguard Worker lws_free(pv);
263*1c60b9acSAndroid Build Coastguard Worker
264*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(p, p1);
265*1c60b9acSAndroid Build Coastguard Worker }
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker /*
268*1c60b9acSAndroid Build Coastguard Worker * We want to support these kinds of qualifier
269*1c60b9acSAndroid Build Coastguard Worker *
270*1c60b9acSAndroid Build Coastguard Worker * myfault true always
271*1c60b9acSAndroid Build Coastguard Worker * myfault(10%) true 10% of the time
272*1c60b9acSAndroid Build Coastguard Worker * myfault(....X X) true when X
273*1c60b9acSAndroid Build Coastguard Worker * myfault2(20..3000) pick a number between 20 and 3000
274*1c60b9acSAndroid Build Coastguard Worker */
275*1c60b9acSAndroid Build Coastguard Worker
276*1c60b9acSAndroid Build Coastguard Worker enum {
277*1c60b9acSAndroid Build Coastguard Worker PARSE_NAME,
278*1c60b9acSAndroid Build Coastguard Worker PARSE_WHEN,
279*1c60b9acSAndroid Build Coastguard Worker PARSE_PC,
280*1c60b9acSAndroid Build Coastguard Worker PARSE_ENDBR,
281*1c60b9acSAndroid Build Coastguard Worker PARSE_COMMA
282*1c60b9acSAndroid Build Coastguard Worker };
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_deserialize(lws_fi_ctx_t * fic,const char * sers)285*1c60b9acSAndroid Build Coastguard Worker lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers)
286*1c60b9acSAndroid Build Coastguard Worker {
287*1c60b9acSAndroid Build Coastguard Worker int state = PARSE_NAME, m;
288*1c60b9acSAndroid Build Coastguard Worker struct lws_tokenize ts;
289*1c60b9acSAndroid Build Coastguard Worker lws_fi_t fi;
290*1c60b9acSAndroid Build Coastguard Worker char nm[64];
291*1c60b9acSAndroid Build Coastguard Worker
292*1c60b9acSAndroid Build Coastguard Worker /*
293*1c60b9acSAndroid Build Coastguard Worker * Go through the comma-separated list of faults
294*1c60b9acSAndroid Build Coastguard Worker * creating them and adding to the lws_context info
295*1c60b9acSAndroid Build Coastguard Worker */
296*1c60b9acSAndroid Build Coastguard Worker
297*1c60b9acSAndroid Build Coastguard Worker lws_tokenize_init(&ts, sers, LWS_TOKENIZE_F_DOT_NONTERM |
298*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_NO_INTEGERS |
299*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_NO_FLOATS |
300*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_EQUALS_NONTERM |
301*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_SLASH_NONTERM |
302*1c60b9acSAndroid Build Coastguard Worker LWS_TOKENIZE_F_MINUS_NONTERM);
303*1c60b9acSAndroid Build Coastguard Worker ts.len = (unsigned int)strlen(sers);
304*1c60b9acSAndroid Build Coastguard Worker if (ts.len < 1 || ts.len > 10240)
305*1c60b9acSAndroid Build Coastguard Worker return;
306*1c60b9acSAndroid Build Coastguard Worker
307*1c60b9acSAndroid Build Coastguard Worker do {
308*1c60b9acSAndroid Build Coastguard Worker ts.e = (int8_t)lws_tokenize(&ts);
309*1c60b9acSAndroid Build Coastguard Worker switch (ts.e) {
310*1c60b9acSAndroid Build Coastguard Worker case LWS_TOKZE_TOKEN:
311*1c60b9acSAndroid Build Coastguard Worker
312*1c60b9acSAndroid Build Coastguard Worker if (state == PARSE_NAME) {
313*1c60b9acSAndroid Build Coastguard Worker /*
314*1c60b9acSAndroid Build Coastguard Worker * One fault to inject looks like, eg,
315*1c60b9acSAndroid Build Coastguard Worker *
316*1c60b9acSAndroid Build Coastguard Worker * vh=xxx/listenskt
317*1c60b9acSAndroid Build Coastguard Worker */
318*1c60b9acSAndroid Build Coastguard Worker
319*1c60b9acSAndroid Build Coastguard Worker memset(&fi, 0, sizeof(fi));
320*1c60b9acSAndroid Build Coastguard Worker
321*1c60b9acSAndroid Build Coastguard Worker lws_strnncpy(nm, ts.token, ts.token_len,
322*1c60b9acSAndroid Build Coastguard Worker sizeof(nm));
323*1c60b9acSAndroid Build Coastguard Worker fi.name = nm;
324*1c60b9acSAndroid Build Coastguard Worker fi.type = LWSFI_ALWAYS;
325*1c60b9acSAndroid Build Coastguard Worker
326*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: name %.*s\n", __func__,
327*1c60b9acSAndroid Build Coastguard Worker (int)ts.token_len, ts.token);
328*1c60b9acSAndroid Build Coastguard Worker
329*1c60b9acSAndroid Build Coastguard Worker /* added later, potentially after (when) */
330*1c60b9acSAndroid Build Coastguard Worker break;
331*1c60b9acSAndroid Build Coastguard Worker }
332*1c60b9acSAndroid Build Coastguard Worker if (state == PARSE_WHEN) {
333*1c60b9acSAndroid Build Coastguard Worker /* it's either numeric (then % or ..num2), or
334*1c60b9acSAndroid Build Coastguard Worker * .X pattern */
335*1c60b9acSAndroid Build Coastguard Worker
336*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: when\n", __func__);
337*1c60b9acSAndroid Build Coastguard Worker
338*1c60b9acSAndroid Build Coastguard Worker if (*ts.token == '.' || *ts.token == 'X') {
339*1c60b9acSAndroid Build Coastguard Worker uint8_t *pat;
340*1c60b9acSAndroid Build Coastguard Worker size_t n;
341*1c60b9acSAndroid Build Coastguard Worker
342*1c60b9acSAndroid Build Coastguard Worker /*
343*1c60b9acSAndroid Build Coastguard Worker * pattern... we need to allocate it
344*1c60b9acSAndroid Build Coastguard Worker */
345*1c60b9acSAndroid Build Coastguard Worker fi.type = LWSFI_PATTERN_ALLOC;
346*1c60b9acSAndroid Build Coastguard Worker pat = lws_zalloc((ts.token_len >> 3) + 1,
347*1c60b9acSAndroid Build Coastguard Worker __func__);
348*1c60b9acSAndroid Build Coastguard Worker if (!pat)
349*1c60b9acSAndroid Build Coastguard Worker return;
350*1c60b9acSAndroid Build Coastguard Worker fi.pattern = pat;
351*1c60b9acSAndroid Build Coastguard Worker fi.count = (uint64_t)ts.token_len;
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < ts.token_len; n++)
354*1c60b9acSAndroid Build Coastguard Worker if (ts.token[n] == 'X')
355*1c60b9acSAndroid Build Coastguard Worker pat[n >> 3] = (uint8_t)(
356*1c60b9acSAndroid Build Coastguard Worker pat[n >> 3] |
357*1c60b9acSAndroid Build Coastguard Worker (1 << (n & 7)));
358*1c60b9acSAndroid Build Coastguard Worker
359*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_notice(pat,
360*1c60b9acSAndroid Build Coastguard Worker (ts.token_len >> 3) + 1);
361*1c60b9acSAndroid Build Coastguard Worker
362*1c60b9acSAndroid Build Coastguard Worker state = PARSE_ENDBR;
363*1c60b9acSAndroid Build Coastguard Worker break;
364*1c60b9acSAndroid Build Coastguard Worker }
365*1c60b9acSAndroid Build Coastguard Worker
366*1c60b9acSAndroid Build Coastguard Worker fi.pre = (uint64_t)atoll(ts.token);
367*1c60b9acSAndroid Build Coastguard Worker
368*1c60b9acSAndroid Build Coastguard Worker for (m = 0; m < (int)ts.token_len - 1; m++)
369*1c60b9acSAndroid Build Coastguard Worker if (ts.token[m] < '0' ||
370*1c60b9acSAndroid Build Coastguard Worker ts.token[m] > '9')
371*1c60b9acSAndroid Build Coastguard Worker break;
372*1c60b9acSAndroid Build Coastguard Worker
373*1c60b9acSAndroid Build Coastguard Worker /*
374*1c60b9acSAndroid Build Coastguard Worker * We can understand num% or num..num
375*1c60b9acSAndroid Build Coastguard Worker */
376*1c60b9acSAndroid Build Coastguard Worker
377*1c60b9acSAndroid Build Coastguard Worker if (m != (int)ts.token_len &&
378*1c60b9acSAndroid Build Coastguard Worker ts.token[m] == '.' &&
379*1c60b9acSAndroid Build Coastguard Worker ts.token[m + 1] == '.') {
380*1c60b9acSAndroid Build Coastguard Worker fi.count = (uint64_t)atoll(
381*1c60b9acSAndroid Build Coastguard Worker &ts.token[m + 2]);
382*1c60b9acSAndroid Build Coastguard Worker fi.type = LWSFI_RANGE;
383*1c60b9acSAndroid Build Coastguard Worker state = PARSE_ENDBR;
384*1c60b9acSAndroid Build Coastguard Worker
385*1c60b9acSAndroid Build Coastguard Worker if (fi.pre >= fi.count) {
386*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: range must have "
387*1c60b9acSAndroid Build Coastguard Worker "smaller first!\n",
388*1c60b9acSAndroid Build Coastguard Worker __func__);
389*1c60b9acSAndroid Build Coastguard Worker }
390*1c60b9acSAndroid Build Coastguard Worker
391*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: range %llx .."
392*1c60b9acSAndroid Build Coastguard Worker "%llx\n", __func__,
393*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)fi.pre,
394*1c60b9acSAndroid Build Coastguard Worker (unsigned long long)fi.count);
395*1c60b9acSAndroid Build Coastguard Worker break;
396*1c60b9acSAndroid Build Coastguard Worker }
397*1c60b9acSAndroid Build Coastguard Worker
398*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: prob %d%%\n", __func__,
399*1c60b9acSAndroid Build Coastguard Worker (int)fi.pre);
400*1c60b9acSAndroid Build Coastguard Worker fi.type = LWSFI_PROBABILISTIC;
401*1c60b9acSAndroid Build Coastguard Worker state = PARSE_PC;
402*1c60b9acSAndroid Build Coastguard Worker break;
403*1c60b9acSAndroid Build Coastguard Worker }
404*1c60b9acSAndroid Build Coastguard Worker break;
405*1c60b9acSAndroid Build Coastguard Worker
406*1c60b9acSAndroid Build Coastguard Worker case LWS_TOKZE_DELIMITER:
407*1c60b9acSAndroid Build Coastguard Worker if (*ts.token == ',') {
408*1c60b9acSAndroid Build Coastguard Worker lws_fi_add(fic, &fi);
409*1c60b9acSAndroid Build Coastguard Worker state = PARSE_NAME;
410*1c60b9acSAndroid Build Coastguard Worker break;
411*1c60b9acSAndroid Build Coastguard Worker }
412*1c60b9acSAndroid Build Coastguard Worker if (*ts.token == '(') {
413*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: (\n", __func__);
414*1c60b9acSAndroid Build Coastguard Worker if (state != PARSE_NAME) {
415*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: misplaced (\n", __func__);
416*1c60b9acSAndroid Build Coastguard Worker return;
417*1c60b9acSAndroid Build Coastguard Worker }
418*1c60b9acSAndroid Build Coastguard Worker state = PARSE_WHEN;
419*1c60b9acSAndroid Build Coastguard Worker break;
420*1c60b9acSAndroid Build Coastguard Worker }
421*1c60b9acSAndroid Build Coastguard Worker if (*ts.token == ')') {
422*1c60b9acSAndroid Build Coastguard Worker if (state != PARSE_ENDBR) {
423*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: misplaced )\n", __func__);
424*1c60b9acSAndroid Build Coastguard Worker return;
425*1c60b9acSAndroid Build Coastguard Worker }
426*1c60b9acSAndroid Build Coastguard Worker state = PARSE_NAME;
427*1c60b9acSAndroid Build Coastguard Worker break;
428*1c60b9acSAndroid Build Coastguard Worker }
429*1c60b9acSAndroid Build Coastguard Worker if (*ts.token == '%') {
430*1c60b9acSAndroid Build Coastguard Worker if (state != PARSE_PC) {
431*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: misplaced %%\n", __func__);
432*1c60b9acSAndroid Build Coastguard Worker return;
433*1c60b9acSAndroid Build Coastguard Worker }
434*1c60b9acSAndroid Build Coastguard Worker state = PARSE_ENDBR;
435*1c60b9acSAndroid Build Coastguard Worker break;
436*1c60b9acSAndroid Build Coastguard Worker }
437*1c60b9acSAndroid Build Coastguard Worker break;
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker case LWS_TOKZE_ENDED:
440*1c60b9acSAndroid Build Coastguard Worker lws_fi_add(fic, &fi);
441*1c60b9acSAndroid Build Coastguard Worker return;
442*1c60b9acSAndroid Build Coastguard Worker
443*1c60b9acSAndroid Build Coastguard Worker default:
444*1c60b9acSAndroid Build Coastguard Worker return;
445*1c60b9acSAndroid Build Coastguard Worker }
446*1c60b9acSAndroid Build Coastguard Worker } while (ts.e > 0);
447*1c60b9acSAndroid Build Coastguard Worker }
448