| | varnish-cache/vmod/vmod_debug_filters.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2012-2019 Varnish Software AS |
2 |
|
* All rights reserved. |
3 |
|
* |
4 |
|
* Author: Poul-Henning Kamp <phk@FreeBSD.org> |
5 |
|
* |
6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
7 |
|
* |
8 |
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
* modification, are permitted provided that the following conditions |
10 |
|
* are met: |
11 |
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
* documentation and/or other materials provided with the distribution. |
16 |
|
* |
17 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
21 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 |
|
* SUCH DAMAGE. |
28 |
|
*/ |
29 |
|
|
30 |
|
#include "config.h" |
31 |
|
|
32 |
|
#include <stdlib.h> |
33 |
|
#include <stdio.h> |
34 |
|
#include <string.h> |
35 |
|
#include <sys/socket.h> |
36 |
|
#include <unistd.h> |
37 |
|
|
38 |
|
#include "cache/cache_varnishd.h" |
39 |
|
#include "cache/cache_filter.h" |
40 |
|
|
41 |
|
#include "vgz.h" |
42 |
|
#include "vsha256.h" |
43 |
|
#include "vtim.h" |
44 |
|
#include "vcc_debug_if.h" |
45 |
|
|
46 |
|
#include "vmod_debug.h" |
47 |
|
|
48 |
|
/**********************************************************************/ |
49 |
|
|
50 |
|
static enum vfp_status v_matchproto_(vfp_pull_f) |
51 |
360 |
xyzzy_vfp_rot13_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p, |
52 |
|
ssize_t *lp) |
53 |
|
{ |
54 |
|
enum vfp_status vp; |
55 |
|
char *q; |
56 |
|
ssize_t l; |
57 |
|
|
58 |
360 |
(void)vfe; |
59 |
360 |
vp = VFP_Suck(vc, p, lp); |
60 |
360 |
if (vp == VFP_ERROR) |
61 |
0 |
return (vp); |
62 |
360 |
q = p; |
63 |
10440 |
for (l = 0; l < *lp; l++, q++) { |
64 |
10080 |
if (*q >= 'A' && *q <= 'Z') |
65 |
1440 |
*q = (((*q - 'A') + 13) % 26) + 'A'; |
66 |
10080 |
if (*q >= 'a' && *q <= 'z') |
67 |
6840 |
*q = (((*q - 'a') + 13) % 26) + 'a'; |
68 |
10080 |
} |
69 |
360 |
return (vp); |
70 |
360 |
} |
71 |
|
|
72 |
|
static const struct vfp xyzzy_vfp_rot13 = { |
73 |
|
.name = "rot13", |
74 |
|
.pull = xyzzy_vfp_rot13_pull, |
75 |
|
}; |
76 |
|
|
77 |
|
/**********************************************************************/ |
78 |
|
|
79 |
|
// deliberately fragmenting the stream to make testing more interesting |
80 |
|
#define ROT13_BUFSZ 8 |
81 |
|
|
82 |
|
static int v_matchproto_(vdp_init_f) |
83 |
560 |
xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
84 |
|
{ |
85 |
|
|
86 |
560 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
87 |
560 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
88 |
560 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
89 |
560 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
90 |
560 |
AN(vdc->clen); |
91 |
|
|
92 |
560 |
AN(priv); |
93 |
|
|
94 |
560 |
*priv = malloc(ROT13_BUFSZ); |
95 |
560 |
if (*priv == NULL) |
96 |
0 |
return (-1); |
97 |
|
|
98 |
560 |
return (0); |
99 |
560 |
} |
100 |
|
|
101 |
|
static int v_matchproto_(vdp_bytes_f) |
102 |
1080 |
xyzzy_vdp_rot13_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
103 |
|
const void *ptr, ssize_t len) |
104 |
|
{ |
105 |
|
char *q; |
106 |
|
const char *pp; |
107 |
1080 |
int i, j, retval = 0; |
108 |
|
|
109 |
1080 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
110 |
1080 |
AN(priv); |
111 |
1080 |
AN(*priv); |
112 |
1080 |
if (len <= 0) |
113 |
240 |
return (VDP_bytes(vdc, act, ptr, len)); |
114 |
840 |
AN(ptr); |
115 |
840 |
if (act != VDP_END) |
116 |
400 |
act = VDP_FLUSH; |
117 |
840 |
q = *priv; |
118 |
840 |
pp = ptr; |
119 |
|
|
120 |
22120 |
for (i = 0, j = 0; j < len; i++, j++) { |
121 |
21280 |
if (pp[j] >= 'A' && pp[j] <= 'Z') |
122 |
1840 |
q[i] = (((pp[j] - 'A') + 13) % 26) + 'A'; |
123 |
19440 |
else if (pp[j] >= 'a' && pp[j] <= 'z') |
124 |
13320 |
q[i] = (((pp[j] - 'a') + 13) % 26) + 'a'; |
125 |
|
else |
126 |
6120 |
q[i] = pp[j]; |
127 |
21280 |
if (i == ROT13_BUFSZ - 1 && j < len - 1) { |
128 |
2200 |
retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ); |
129 |
2200 |
if (retval != 0) |
130 |
0 |
return (retval); |
131 |
2200 |
i = -1; |
132 |
2200 |
} |
133 |
21280 |
} |
134 |
840 |
if (i >= 0) |
135 |
840 |
retval = VDP_bytes(vdc, act, q, i); |
136 |
840 |
return (retval); |
137 |
1080 |
} |
138 |
|
|
139 |
|
static int v_matchproto_(vdp_fini_f) |
140 |
560 |
xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv) |
141 |
|
{ |
142 |
560 |
(void)vdc; |
143 |
560 |
AN(priv); |
144 |
560 |
free(*priv); |
145 |
560 |
*priv = NULL; |
146 |
560 |
return (0); |
147 |
|
} |
148 |
|
|
149 |
|
static const struct vdp xyzzy_vdp_rot13 = { |
150 |
|
.name = "rot13", |
151 |
|
.init = xyzzy_vdp_rot13_init, |
152 |
|
.bytes = xyzzy_vdp_rot13_bytes, |
153 |
|
.fini = xyzzy_vdp_rot13_fini, |
154 |
|
}; |
155 |
|
|
156 |
|
VCL_VOID v_matchproto_(td_debug_rot104) |
157 |
40 |
xyzzy_rot104(VRT_CTX) |
158 |
|
{ |
159 |
|
|
160 |
40 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
161 |
|
// This should fail |
162 |
40 |
AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13)); |
163 |
40 |
} |
164 |
|
|
165 |
|
/********************************************************************** |
166 |
|
* vdp debug_chunked: force http1 chunked encoding by removing the |
167 |
|
* Content-Length header |
168 |
|
* |
169 |
|
* this happens in a VDP because cnt_transmit() runs after VCL and |
170 |
|
* restores it |
171 |
|
*/ |
172 |
|
|
173 |
|
static int v_matchproto_(vdp_init_f) |
174 |
80 |
xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
175 |
|
{ |
176 |
|
|
177 |
80 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
178 |
80 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
179 |
80 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
180 |
80 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
181 |
80 |
AN(vdc->clen); |
182 |
80 |
AN(priv); |
183 |
|
|
184 |
80 |
http_Unset(vdc->hp, H_Content_Length); |
185 |
80 |
*vdc->clen = -1; |
186 |
|
|
187 |
80 |
return (1); |
188 |
|
} |
189 |
|
|
190 |
|
static const struct vdp xyzzy_vdp_chunked = { |
191 |
|
.name = "debug.chunked", |
192 |
|
.init = xyzzy_vdp_chunked_init, |
193 |
|
}; |
194 |
|
|
195 |
|
/********************************************************************** |
196 |
|
* pedantic tests of the VDP API: |
197 |
|
* - assert that we see a VDP_END |
198 |
|
* - assert that _fini gets called before the task ends |
199 |
|
* |
200 |
|
* note: |
201 |
|
* we could lookup our own vdpe in _fini and check for vdpe->end == VDP_END |
202 |
|
* yet that would cross the API |
203 |
|
*/ |
204 |
|
|
205 |
|
enum vdp_state_e { |
206 |
|
VDPS_NULL = 0, |
207 |
|
VDPS_INIT, // _init called |
208 |
|
VDPS_BYTES, // _bytes called act != VDP_END |
209 |
|
VDPS_END, // _bytes called act == VDP_END |
210 |
|
VDPS_FINI // _fini called |
211 |
|
}; |
212 |
|
|
213 |
|
struct vdp_state_s { |
214 |
|
unsigned magic; |
215 |
|
#define VDP_STATE_MAGIC 0x57c8d309 |
216 |
|
enum vdp_state_e state; |
217 |
|
}; |
218 |
|
|
219 |
|
static void v_matchproto_(vmod_priv_fini_f) |
220 |
7560 |
priv_pedantic_fini(VRT_CTX, void *priv) |
221 |
|
{ |
222 |
|
struct vdp_state_s *vdps; |
223 |
|
|
224 |
7560 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
225 |
7560 |
CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC); |
226 |
|
|
227 |
7560 |
assert(vdps->state == VDPS_FINI); |
228 |
7560 |
} |
229 |
|
|
230 |
|
static const struct vmod_priv_methods priv_pedantic_methods[1] = {{ |
231 |
|
.magic = VMOD_PRIV_METHODS_MAGIC, |
232 |
|
.type = "debug_vdp_pedantic", |
233 |
|
.fini = priv_pedantic_fini |
234 |
|
}}; |
235 |
|
|
236 |
|
static int v_matchproto_(vdp_init_f) |
237 |
7880 |
xyzzy_pedantic_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
238 |
|
{ |
239 |
|
struct vdp_state_s *vdps; |
240 |
|
struct vmod_priv *p; |
241 |
|
|
242 |
7880 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
243 |
7880 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
244 |
7880 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
245 |
7880 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
246 |
7880 |
AN(vdc->clen); |
247 |
7880 |
AN(priv); |
248 |
|
|
249 |
15440 |
WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC); |
250 |
7880 |
if (vdps == NULL) |
251 |
320 |
return (-1); |
252 |
7560 |
assert(vdps->state == VDPS_NULL); |
253 |
|
|
254 |
7560 |
p = VRT_priv_task(ctx, (void *)vdc); |
255 |
7560 |
if (p == NULL) |
256 |
0 |
return (-1); |
257 |
7560 |
p->priv = vdps; |
258 |
7560 |
p->methods = priv_pedantic_methods; |
259 |
|
|
260 |
7560 |
*priv = vdps; |
261 |
|
|
262 |
7560 |
vdps->state = VDPS_INIT; |
263 |
|
|
264 |
7560 |
return (0); |
265 |
7880 |
} |
266 |
|
|
267 |
|
static int v_matchproto_(vdp_bytes_f) |
268 |
9396 |
xyzzy_pedantic_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
269 |
|
const void *ptr, ssize_t len) |
270 |
|
{ |
271 |
|
struct vdp_state_s *vdps; |
272 |
|
|
273 |
9396 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC); |
274 |
9396 |
assert(vdps->state >= VDPS_INIT); |
275 |
9396 |
assert(vdps->state < VDPS_END); |
276 |
|
|
277 |
9396 |
if (act == VDP_END) |
278 |
2440 |
vdps->state = VDPS_END; |
279 |
|
else |
280 |
6956 |
vdps->state = VDPS_BYTES; |
281 |
|
|
282 |
9396 |
return (VDP_bytes(vdc, act, ptr, len)); |
283 |
|
} |
284 |
|
|
285 |
|
static int v_matchproto_(vdp_fini_f) |
286 |
7880 |
xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv) |
287 |
|
{ |
288 |
|
struct vdp_state_s *vdps; |
289 |
|
|
290 |
7880 |
(void) vdc; |
291 |
7880 |
AN(priv); |
292 |
7880 |
if (*priv == NULL) |
293 |
320 |
return (0); |
294 |
7560 |
TAKE_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC); |
295 |
7560 |
assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END); |
296 |
7560 |
vdps->state = VDPS_FINI; |
297 |
|
|
298 |
7560 |
return (0); |
299 |
7880 |
} |
300 |
|
|
301 |
|
static const struct vdp xyzzy_vdp_pedantic = { |
302 |
|
.name = "debug.pedantic", |
303 |
|
.init = xyzzy_pedantic_init, |
304 |
|
.bytes = xyzzy_pedantic_bytes, |
305 |
|
.fini = xyzzy_pedantic_fini, |
306 |
|
}; |
307 |
|
|
308 |
|
/********************************************************************** |
309 |
|
* |
310 |
|
* this trivial copy/paste/edit filter (of rot13) was specifically made for |
311 |
|
* someone who added a DBG_SLOW_BEREQ debug flag. It should actually be turned |
312 |
|
* in a proper "bandwidth control" filter, but that exceeds an evening's work, |
313 |
|
* so it's kept for later |
314 |
|
*/ |
315 |
|
|
316 |
|
static enum vfp_status v_matchproto_(vfp_pull_f) |
317 |
0 |
xyzzy_vfp_slow_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p, |
318 |
|
ssize_t *lp) |
319 |
|
{ |
320 |
|
|
321 |
0 |
(void)vfe; |
322 |
0 |
VTIM_sleep(1.0); |
323 |
0 |
return (VFP_Suck(vc, p, lp)); |
324 |
|
} |
325 |
|
|
326 |
|
static const struct vfp xyzzy_vfp_slow = { |
327 |
|
.name = "debug.slow", |
328 |
|
.pull = xyzzy_vfp_slow_pull, |
329 |
|
}; |
330 |
|
|
331 |
|
/**********************************************************************/ |
332 |
|
|
333 |
|
static int v_matchproto_(vdp_bytes_f) |
334 |
160 |
xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
335 |
|
const void *ptr, ssize_t len) |
336 |
|
{ |
337 |
|
|
338 |
160 |
(void)priv; |
339 |
160 |
VTIM_sleep(1.0); |
340 |
160 |
return (VDP_bytes(vdc, act, ptr, len)); |
341 |
|
} |
342 |
|
|
343 |
|
static const struct vdp xyzzy_vdp_slow = { |
344 |
|
.name = "debug.slow", |
345 |
|
.bytes = xyzzy_vdp_slow_bytes |
346 |
|
}; |
347 |
|
|
348 |
|
/* |
349 |
|
* checksum VDP: |
350 |
|
* test that the stream of bytes has a certain checksum and either log |
351 |
|
* or panic |
352 |
|
* |
353 |
|
* The sha256 and crc32 variants are basically identical, but the amount of |
354 |
|
* code does not justify generalizing. (slink) |
355 |
|
*/ |
356 |
|
|
357 |
|
enum vdp_chk_mode_e { |
358 |
|
//lint -esym(749, vdp_chk_mode_e::VDP_CHK_INVAL) deliberately not referenced |
359 |
|
VDP_CHK_INVAL = 0, |
360 |
|
VDP_CHK_LOG, |
361 |
|
VDP_CHK_PANIC, |
362 |
|
VDP_CHK_PANIC_UNLESS_ERROR |
363 |
|
}; |
364 |
|
|
365 |
|
struct vdp_chksha256_cfg_s { |
366 |
|
unsigned magic; |
367 |
|
#define VDP_CHKSHA256_CFG_MAGIC 0x624f5b32 |
368 |
|
enum vdp_chk_mode_e mode; |
369 |
|
unsigned char expected[VSHA256_DIGEST_LENGTH]; |
370 |
|
}; |
371 |
|
|
372 |
|
struct vdp_chkcrc32_cfg_s { |
373 |
|
unsigned magic; |
374 |
|
#define VDP_CHKCRC32_CFG_MAGIC 0x5a7a835c |
375 |
|
enum vdp_chk_mode_e mode; |
376 |
|
uint32_t expected; |
377 |
|
}; |
378 |
|
|
379 |
|
struct vdp_chksha256_s { |
380 |
|
unsigned magic; |
381 |
|
#define VDP_CHKSHA256_MAGIC 0x6856e913 |
382 |
|
unsigned called; |
383 |
|
size_t bytes; |
384 |
|
struct VSHA256Context cx[1]; |
385 |
|
struct vdp_chksha256_cfg_s *cfg; |
386 |
|
}; |
387 |
|
|
388 |
|
struct vdp_chkcrc32_s { |
389 |
|
unsigned magic; |
390 |
|
#define VDP_CHKCRC32_MAGIC 0x15c03d3c |
391 |
|
unsigned called; |
392 |
|
size_t bytes; |
393 |
|
uint32_t crc; |
394 |
|
struct vdp_chkcrc32_cfg_s *cfg; |
395 |
|
}; |
396 |
|
|
397 |
|
static const void * const chksha256_priv_id = &chksha256_priv_id; |
398 |
|
static const void * const chkcrc32_priv_id = &chkcrc32_priv_id; |
399 |
|
|
400 |
|
static int v_matchproto_(vdp_init_f) |
401 |
0 |
xyzzy_chksha256_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
402 |
|
{ |
403 |
|
struct vdp_chksha256_s *vdps; |
404 |
|
struct vmod_priv *p; |
405 |
|
|
406 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
407 |
0 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
408 |
0 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
409 |
0 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
410 |
0 |
AN(vdc->clen); |
411 |
0 |
AN(priv); |
412 |
|
|
413 |
0 |
WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC); |
414 |
0 |
if (vdps == NULL) |
415 |
0 |
return (-1); |
416 |
0 |
VSHA256_Init(vdps->cx); |
417 |
|
|
418 |
0 |
p = VRT_priv_task_get(ctx, chksha256_priv_id); |
419 |
0 |
if (p == NULL) |
420 |
0 |
return (-1); |
421 |
|
|
422 |
0 |
assert(p->len == sizeof(struct vdp_chksha256_cfg_s)); |
423 |
0 |
CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC); |
424 |
0 |
*priv = vdps; |
425 |
|
|
426 |
0 |
return (0); |
427 |
0 |
} |
428 |
|
|
429 |
|
static int v_matchproto_(vdp_init_f) |
430 |
0 |
xyzzy_chkcrc32_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
431 |
|
{ |
432 |
|
struct vdp_chkcrc32_s *vdps; |
433 |
|
struct vmod_priv *p; |
434 |
|
|
435 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
436 |
0 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
437 |
0 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
438 |
0 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
439 |
0 |
AN(vdc->clen); |
440 |
0 |
AN(priv); |
441 |
|
|
442 |
0 |
WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC); |
443 |
0 |
if (vdps == NULL) |
444 |
0 |
return (-1); |
445 |
0 |
vdps->crc = crc32(0L, Z_NULL, 0); |
446 |
|
|
447 |
0 |
p = VRT_priv_task_get(ctx, chkcrc32_priv_id); |
448 |
0 |
if (p == NULL) |
449 |
0 |
return (-1); |
450 |
|
|
451 |
0 |
assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s)); |
452 |
0 |
CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC); |
453 |
0 |
*priv = vdps; |
454 |
|
|
455 |
0 |
return (0); |
456 |
0 |
} |
457 |
|
|
458 |
|
static int v_matchproto_(vdp_bytes_f) |
459 |
0 |
xyzzy_chksha256_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
460 |
|
const void *ptr, ssize_t len) |
461 |
|
{ |
462 |
|
struct vdp_chksha256_s *vdps; |
463 |
|
|
464 |
0 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC); |
465 |
0 |
VSHA256_Update(vdps->cx, ptr, len); |
466 |
0 |
vdps->called++; |
467 |
0 |
vdps->bytes += len; |
468 |
0 |
return (VDP_bytes(vdc, act, ptr, len)); |
469 |
|
} |
470 |
|
|
471 |
|
static int v_matchproto_(vdp_bytes_f) |
472 |
0 |
xyzzy_chkcrc32_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
473 |
|
const void *ptr, ssize_t len) |
474 |
|
{ |
475 |
|
struct vdp_chkcrc32_s *vdps; |
476 |
|
|
477 |
0 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC); |
478 |
0 |
if (len > 0) |
479 |
0 |
vdps->crc = crc32(vdps->crc, ptr, len); |
480 |
0 |
vdps->called++; |
481 |
0 |
vdps->bytes += len; |
482 |
0 |
return (VDP_bytes(vdc, act, ptr, len)); |
483 |
|
} |
484 |
|
|
485 |
|
static int v_matchproto_(vdp_fini_f) |
486 |
0 |
xyzzy_chksha256_fini(struct vdp_ctx *vdc, void **priv) |
487 |
|
{ |
488 |
|
unsigned char digest[VSHA256_DIGEST_LENGTH]; |
489 |
|
enum vdp_chk_mode_e mode; |
490 |
|
struct vdp_chksha256_s *vdps; |
491 |
|
struct vsb *vsb; |
492 |
|
int r; |
493 |
|
|
494 |
0 |
(void) vdc; |
495 |
0 |
AN(priv); |
496 |
0 |
if (*priv == NULL) |
497 |
0 |
return (0); |
498 |
0 |
TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKSHA256_MAGIC); |
499 |
|
|
500 |
0 |
VSHA256_Final(digest, vdps->cx); |
501 |
0 |
r = memcmp(digest, vdps->cfg->expected, sizeof digest); |
502 |
0 |
if (r == 0) |
503 |
0 |
return (0); |
504 |
|
|
505 |
0 |
mode = vdps->cfg->mode; |
506 |
0 |
if (mode == VDP_CHK_PANIC_UNLESS_ERROR) |
507 |
0 |
mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC; |
508 |
|
|
509 |
0 |
if (mode == VDP_CHK_LOG) { |
510 |
0 |
VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch"); |
511 |
|
|
512 |
0 |
vsb = VSB_new_auto(); |
513 |
0 |
AN(vsb); |
514 |
0 |
VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX); |
515 |
0 |
AZ(VSB_finish(vsb)); |
516 |
0 |
VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb)); |
517 |
|
|
518 |
0 |
VSB_clear(vsb); |
519 |
0 |
VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX); |
520 |
0 |
AZ(VSB_finish(vsb)); |
521 |
0 |
VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb)); |
522 |
0 |
VSB_destroy(&vsb); |
523 |
0 |
} |
524 |
0 |
else if (mode == VDP_CHK_PANIC) |
525 |
0 |
WRONG("body checksum"); |
526 |
|
else |
527 |
0 |
WRONG("mode"); |
528 |
|
|
529 |
0 |
return (0); |
530 |
0 |
} |
531 |
|
|
532 |
|
static int v_matchproto_(vdp_fini_f) |
533 |
0 |
xyzzy_chkcrc32_fini(struct vdp_ctx *vdc, void **priv) |
534 |
|
{ |
535 |
|
enum vdp_chk_mode_e mode; |
536 |
|
struct vdp_chkcrc32_s *vdps; |
537 |
|
|
538 |
0 |
(void) vdc; |
539 |
0 |
AN(priv); |
540 |
0 |
if (*priv == NULL) |
541 |
0 |
return (0); |
542 |
0 |
TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKCRC32_MAGIC); |
543 |
|
|
544 |
0 |
if (vdps->crc == vdps->cfg->expected) |
545 |
0 |
return (0); |
546 |
|
|
547 |
0 |
mode = vdps->cfg->mode; |
548 |
0 |
if (mode == VDP_CHK_PANIC_UNLESS_ERROR) |
549 |
0 |
mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC; |
550 |
|
|
551 |
0 |
if (mode == VDP_CHK_LOG) { |
552 |
0 |
VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch"); |
553 |
0 |
VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc); |
554 |
0 |
VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected); |
555 |
0 |
} |
556 |
0 |
else if (mode == VDP_CHK_PANIC) |
557 |
0 |
WRONG("body checksum"); |
558 |
|
else |
559 |
0 |
WRONG("mode"); |
560 |
|
|
561 |
0 |
return (0); |
562 |
0 |
} |
563 |
|
|
564 |
|
static const struct vdp xyzzy_vdp_chksha256 = { |
565 |
|
.name = "debug.chksha256", |
566 |
|
.init = xyzzy_chksha256_init, |
567 |
|
.bytes = xyzzy_chksha256_bytes, |
568 |
|
.fini = xyzzy_chksha256_fini, |
569 |
|
}; |
570 |
|
|
571 |
|
static const struct vdp xyzzy_vdp_chkcrc32 = { |
572 |
|
.name = "debug.chkcrc32", |
573 |
|
.init = xyzzy_chkcrc32_init, |
574 |
|
.bytes = xyzzy_chkcrc32_bytes, |
575 |
|
.fini = xyzzy_chkcrc32_fini, |
576 |
|
}; |
577 |
|
|
578 |
|
#define chkcfg(ws, cfg, magic, id, mode_e) do { \ |
579 |
|
struct vmod_priv *p = VRT_priv_task(ctx, id); \ |
580 |
|
\ |
581 |
|
XXXAN(p); \ |
582 |
|
if (p->priv == NULL) { \ |
583 |
|
p->priv = WS_Alloc(ws, sizeof *cfg); \ |
584 |
|
p->len = sizeof *cfg; \ |
585 |
|
} \ |
586 |
|
cfg = p->priv; \ |
587 |
|
INIT_OBJ(cfg, magic); \ |
588 |
|
if (mode_e == VENUM(log)) \ |
589 |
|
cfg->mode = VDP_CHK_LOG; \ |
590 |
|
else if (mode_e == VENUM(panic)) \ |
591 |
|
cfg->mode = VDP_CHK_PANIC; \ |
592 |
|
else if (mode_e == VENUM(panic_unless_error)) \ |
593 |
|
cfg->mode = VDP_CHK_PANIC_UNLESS_ERROR; \ |
594 |
|
else \ |
595 |
|
WRONG("mode"); \ |
596 |
|
} while(0) |
597 |
|
|
598 |
|
VCL_VOID v_matchproto_(td_xyzzy_debug_chksha256) |
599 |
0 |
xyzzy_chksha256(VRT_CTX, VCL_BLOB blob, VCL_ENUM mode_e) |
600 |
|
{ |
601 |
|
struct vdp_chksha256_cfg_s *cfg; |
602 |
|
size_t l; |
603 |
|
|
604 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
605 |
0 |
AN(blob); |
606 |
0 |
XXXAN(blob->blob); |
607 |
0 |
XXXAN(blob->len); |
608 |
|
|
609 |
0 |
chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e); |
610 |
|
|
611 |
0 |
l = blob->len; |
612 |
0 |
if (l > sizeof cfg->expected) |
613 |
0 |
l = sizeof cfg->expected; |
614 |
0 |
memcpy(cfg->expected, blob->blob, l); |
615 |
|
|
616 |
0 |
} |
617 |
|
|
618 |
|
VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32) |
619 |
0 |
xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e) |
620 |
|
{ |
621 |
|
struct vdp_chkcrc32_cfg_s *cfg; |
622 |
|
|
623 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
624 |
|
|
625 |
0 |
chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e); |
626 |
|
|
627 |
0 |
if (expected < 0) |
628 |
0 |
expected = 0; |
629 |
0 |
cfg->expected = (uintmax_t)expected % UINT32_MAX; |
630 |
0 |
} |
631 |
|
|
632 |
|
/********************************************************************** |
633 |
|
* reserve thread_workspace |
634 |
|
*/ |
635 |
|
|
636 |
|
static int v_matchproto_(vdp_init_f) |
637 |
40 |
xyzzy_awshog_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
638 |
|
{ |
639 |
|
struct ws *aws; |
640 |
|
unsigned u; |
641 |
|
|
642 |
40 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
643 |
40 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
644 |
40 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
645 |
40 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
646 |
40 |
AN(vdc->clen); |
647 |
40 |
AN(priv); |
648 |
|
|
649 |
40 |
if (ctx->req != NULL) |
650 |
0 |
aws = ctx->req->wrk->aws; |
651 |
40 |
else if (ctx->bo != NULL) |
652 |
40 |
aws = ctx->bo->wrk->aws; |
653 |
|
else |
654 |
0 |
WRONG("neither req nor bo"); |
655 |
|
|
656 |
40 |
u = WS_ReserveAll(aws); |
657 |
40 |
WS_Release(aws, 0); |
658 |
40 |
(void) WS_Alloc(aws, u); |
659 |
40 |
return (1); |
660 |
|
} |
661 |
|
|
662 |
|
static const struct vdp xyzzy_vdp_awshog = { |
663 |
|
.name = "debug.awshog", |
664 |
|
.init = xyzzy_awshog_init |
665 |
|
}; |
666 |
|
|
667 |
|
void |
668 |
3880 |
debug_add_filters(VRT_CTX) |
669 |
|
{ |
670 |
3880 |
AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13)); |
671 |
3880 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic)); |
672 |
3880 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked)); |
673 |
3880 |
AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow)); |
674 |
3880 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256)); |
675 |
3880 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32)); |
676 |
3880 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_awshog)); |
677 |
3880 |
} |
678 |
|
|
679 |
|
void |
680 |
920 |
debug_remove_filters(VRT_CTX) |
681 |
|
{ |
682 |
920 |
VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow); |
683 |
920 |
VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13); |
684 |
920 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic); |
685 |
920 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked); |
686 |
920 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256); |
687 |
920 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32); |
688 |
920 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_awshog); |
689 |
920 |
} |