vinyl-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_int.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 189
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 189
        (void)vfe;
59 189
        vp = VFP_Suck(vc, p, lp);
60 189
        if (vp == VFP_ERROR)
61 0
                return (vp);
62 189
        q = p;
63 5481
        for (l = 0; l < *lp; l++, q++) {
64 5292
                if (*q >= 'A' && *q <= 'Z')
65 756
                        *q = (((*q - 'A') + 13) % 26) + 'A';
66 5292
                if (*q >= 'a' && *q <= 'z')
67 3591
                        *q = (((*q - 'a') + 13) % 26) + 'a';
68 5292
        }
69 189
        return (vp);
70 189
}
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 rot13_init_fail = 0;
83
84
void
85 42
xyzzy_rot13_fail_init(VRT_CTX)
86
{
87
88 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
89 42
        rot13_init_fail = 1;
90 42
}
91
92
static int v_matchproto_(vdp_init_f)
93 567
xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
94
{
95
96 567
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
97 567
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
98 567
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
99 567
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
100 567
        AN(vdc->clen);
101
102 567
        AN(priv);
103
104 567
        if (rot13_init_fail)
105 42
                return (-1);
106 525
        *priv = malloc(ROT13_BUFSZ);
107 525
        if (*priv == NULL)
108 0
                return (-1);
109
110 525
        return (0);
111 567
}
112
113
static int v_matchproto_(vdp_bytes_f)
114 798
xyzzy_vdp_rot13_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
115
    const void *ptr, ssize_t len)
116
{
117
        char *q;
118
        const char *pp;
119 798
        int i, j, retval = 0;
120
121 798
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
122 798
        AN(priv);
123 798
        AN(*priv);
124 798
        if (len <= 0)
125 126
                return (VDP_bytes(vdc, act, ptr, len));
126 672
        AN(ptr);
127 672
        if (act != VDP_END)
128 210
                act = VDP_FLUSH;
129 672
        q = *priv;
130 672
        pp = ptr;
131
132 2215584
        for (i = 0, j = 0; j < len; i++, j++) {
133 2214912
                if (pp[j] >= 'A' && pp[j] <= 'Z')
134 595282
                        q[i] = (((pp[j] - 'A') + 13) % 26) + 'A';
135 1619630
                else if (pp[j] >= 'a' && pp[j] <= 'z')
136 598678
                        q[i] = (((pp[j] - 'a') + 13) % 26) + 'a';
137
                else
138 1020952
                        q[i] = pp[j];
139 2214912
                if (i == ROT13_BUFSZ - 1 && j < len - 1) {
140 276528
                        retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ);
141 276528
                        if (retval != 0)
142 0
                                return (retval);
143 276528
                        i = -1;
144 276528
                }
145 2214912
        }
146 672
        if (i >= 0)
147 672
                retval = VDP_bytes(vdc, act, q, i);
148 672
        return (retval);
149 798
}
150
151
static int v_matchproto_(vdp_fini_f)
152 525
xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv)
153
{
154 525
        (void)vdc;
155 525
        AN(priv);
156 525
        AN(*priv);
157 525
        free(*priv);
158 525
        *priv = NULL;
159 525
        return (0);
160
}
161
162
static const struct vdp xyzzy_vdp_rot13 = {
163
        .name  = "rot13",
164
        .init  = xyzzy_vdp_rot13_init,
165
        .bytes = xyzzy_vdp_rot13_bytes,
166
        .fini  = xyzzy_vdp_rot13_fini,
167
};
168
169
VCL_VOID v_matchproto_(td_debug_rot104)
170 21
xyzzy_rot104(VRT_CTX)
171
{
172
173 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
174
        // This should fail
175 21
        AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
176 21
}
177
178
/**********************************************************************
179
 * vdp debug_chunked: force http1 chunked encoding by removing the
180
 * Content-Length header
181
 *
182
 * this happens in a VDP because cnt_transmit() runs after VCL and
183
 * restores it
184
 */
185
186
static int v_matchproto_(vdp_init_f)
187 672
xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
188
{
189
190 672
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
191 672
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
192 672
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
193 672
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
194 672
        AN(vdc->clen);
195 672
        AN(priv);
196
197 672
        *vdc->clen = -1;
198
199 672
        return (1);
200
}
201
202
static const struct vdp xyzzy_vdp_chunked = {
203
        .name  = "debug.chunked",
204
        .init  = xyzzy_vdp_chunked_init,
205
};
206
207
/**********************************************************************
208
 * pedantic tests of the VDP API:
209
 * - assert that we see a VDP_END
210
 * - assert that _fini gets called before the task ends
211
 *
212
 * note:
213
 * we could lookup our own vdpe in _fini and check for vdpe->end == VDP_END
214
 * yet that would cross the API
215
 */
216
217
enum vdp_state_e {
218
        VDPS_NULL = 0,
219
        VDPS_INIT,      // _init called
220
        VDPS_BYTES,     // _bytes called act != VDP_END
221
        VDPS_END,       // _bytes called act == VDP_END
222
        VDPS_FINI       // _fini called
223
};
224
225
struct vdp_state_s {
226
        unsigned                magic;
227
#define VDP_STATE_MAGIC 0x57c8d309
228
        enum vdp_state_e        state;
229
};
230
231
static void v_matchproto_(vmod_priv_fini_f)
232 4200
priv_pedantic_fini(VRT_CTX, void *priv)
233
{
234
        struct vdp_state_s *vdps;
235
236 4200
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
237 4200
        CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
238
239 4200
        assert(vdps->state == VDPS_FINI);
240 4200
}
241
242
static const struct vmod_priv_methods priv_pedantic_methods[1] = {{
243
        .magic = VMOD_PRIV_METHODS_MAGIC,
244
        .type = "debug_vdp_pedantic",
245
        .fini = priv_pedantic_fini
246
}};
247
248
static int v_matchproto_(vdp_init_f)
249 4368
xyzzy_pedantic_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
250
{
251
        struct vdp_state_s *vdps;
252
        struct vmod_priv *p;
253
254 4368
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
255 4368
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
256 4368
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
257 4368
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
258 4368
        AN(vdc->clen);
259 4368
        AN(priv);
260
261 8568
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC);
262 4368
        if (vdps == NULL)
263 168
                return (-1);
264 4200
        assert(vdps->state == VDPS_NULL);
265
266 4200
        p = VRT_priv_task(ctx, (void *)vdc);
267 4200
        if (p == NULL)
268 0
                return (-1);
269 4200
        p->priv = vdps;
270 4200
        p->methods = priv_pedantic_methods;
271
272 4200
        *priv = vdps;
273
274 4200
        vdps->state = VDPS_INIT;
275
276 4200
        return (0);
277 4368
}
278
279
static int v_matchproto_(vdp_bytes_f)
280 5313
xyzzy_pedantic_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
281
    const void *ptr, ssize_t len)
282
{
283
        struct vdp_state_s *vdps;
284
285 5313
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
286 5313
        assert(vdps->state >= VDPS_INIT);
287 5313
        assert(vdps->state < VDPS_END);
288
289 5313
        if (act == VDP_END)
290 1470
                vdps->state = VDPS_END;
291
        else
292 3843
                vdps->state = VDPS_BYTES;
293
294 5313
        return (VDP_bytes(vdc, act, ptr, len));
295
}
296
297
static int v_matchproto_(vdp_fini_f)
298 4200
xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv)
299
{
300
        struct vdp_state_s *vdps;
301
302 4200
        (void) vdc;
303 4200
        AN(priv);
304 4200
        if (*priv == NULL)
305 0
                return (0);
306 4200
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
307 4200
        assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END);
308 4200
        vdps->state = VDPS_FINI;
309
310 4200
        return (0);
311 4200
}
312
313
static const struct vdp xyzzy_vdp_pedantic = {
314
        .name  = "debug.pedantic",
315
        .init  = xyzzy_pedantic_init,
316
        .bytes = xyzzy_pedantic_bytes,
317
        .fini  = xyzzy_pedantic_fini,
318
};
319
320
/**********************************************************************
321
 *
322
 * this trivial copy/paste/edit filter (of rot13) was specifically made for
323
 * someone who added a DBG_SLOW_BEREQ debug flag. It should actually be turned
324
 * in a proper "bandwidth control" filter, but that exceeds an evening's work,
325
 * so it's kept for later
326
 */
327
328
static enum vfp_status v_matchproto_(vfp_pull_f)
329 0
xyzzy_vfp_slow_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
330
    ssize_t *lp)
331
{
332
333 0
        (void)vfe;
334 0
        VTIM_sleep(1.0);
335 0
        return (VFP_Suck(vc, p, lp));
336
}
337
338
static const struct vfp xyzzy_vfp_slow = {
339
        .name = "debug.slow",
340
        .pull = xyzzy_vfp_slow_pull,
341
};
342
343
/**********************************************************************/
344
345
static int v_matchproto_(vdp_bytes_f)
346 84
xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
347
    const void *ptr, ssize_t len)
348
{
349
350 84
        (void)priv;
351 84
        VTIM_sleep(1.0);
352 84
        return (VDP_bytes(vdc, act, ptr, len));
353
}
354
355
static const struct vdp xyzzy_vdp_slow = {
356
        .name  = "debug.slow",
357
        .bytes = xyzzy_vdp_slow_bytes
358
};
359
360
/*
361
 * check VDPs:
362
 *
363
 * test that the stream of bytes has a certain checksum or length and either log
364
 * or panic
365
 *
366
 * The sha256 and crc32 variants are basically identical, but the amount of
367
 * code does not justify generalizing. (slink)
368
 */
369
370
enum vdp_chk_mode_e {
371
        //lint -esym(749, vdp_chk_mode_e::VDP_CHK_INVAL) deliberately not referenced
372
        VDP_CHK_INVAL = 0,
373
        VDP_CHK_LOG,
374
        VDP_CHK_PANIC,
375
        VDP_CHK_PANIC_UNLESS_ERROR
376
};
377
378
struct vdp_chksha256_cfg_s {
379
        unsigned                        magic;
380
#define VDP_CHKSHA256_CFG_MAGIC         0x624f5b32
381
        enum vdp_chk_mode_e             mode;
382
        unsigned char                   expected[VSHA256_DIGEST_LENGTH];
383
};
384
385
struct vdp_chkcrc32_cfg_s {
386
        unsigned                        magic;
387
#define VDP_CHKCRC32_CFG_MAGIC          0x5a7a835c
388
        enum vdp_chk_mode_e             mode;
389
        uint32_t                        expected;
390
};
391
392
struct vdp_chklen_cfg_s {
393
        unsigned                        magic;
394
#define VDP_CHKLEN_CFG_MAGIC            0x08cf3426
395
        enum vdp_chk_mode_e             mode;
396
        size_t                          expected;
397
};
398
399
struct vdp_chksha256_s {
400
        unsigned                        magic;
401
#define VDP_CHKSHA256_MAGIC             0x6856e913
402
        unsigned                        called;
403
        size_t                          bytes;
404
        struct VSHA256Context           cx[1];
405
        struct vdp_chksha256_cfg_s      *cfg;
406
};
407
408
struct vdp_chkcrc32_s {
409
        unsigned                        magic;
410
#define VDP_CHKCRC32_MAGIC              0x15c03d3c
411
        unsigned                        called;
412
        size_t                          bytes;
413
        uint32_t                        crc;
414
        struct vdp_chkcrc32_cfg_s       *cfg;
415
};
416
417
struct vdp_chklen_s {
418
        unsigned                        magic;
419
#define VDP_CHKLEN_MAGIC                0x029811f5
420
        unsigned                        called;
421
        size_t                          bytes;
422
        struct vdp_chklen_cfg_s         *cfg;
423
};
424
425
static const void * const chksha256_priv_id = &chksha256_priv_id;
426
static const void * const chkcrc32_priv_id = &chkcrc32_priv_id;
427
static const void * const chklen_priv_id = &chklen_priv_id;
428
429
static int v_matchproto_(vdp_init_f)
430 42
xyzzy_chksha256_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
431
{
432
        struct vdp_chksha256_s *vdps;
433
        struct vmod_priv *p;
434
435 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
436 42
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
437 42
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
438 42
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
439 42
        AN(vdc->clen);
440 42
        AN(priv);
441
442 84
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC);
443 42
        if (vdps == NULL)
444 0
                return (-1);
445 42
        VSHA256_Init(vdps->cx);
446
447 42
        p = VRT_priv_task_get(ctx, chksha256_priv_id);
448 42
        if (p == NULL)
449 0
                return (-1);
450
451 42
        assert(p->len == sizeof(struct vdp_chksha256_cfg_s));
452 42
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC);
453 42
        *priv = vdps;
454
455 42
        return (0);
456 42
}
457
458
static int v_matchproto_(vdp_init_f)
459 42
xyzzy_chkcrc32_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
460
{
461
        struct vdp_chkcrc32_s *vdps;
462
        struct vmod_priv *p;
463
464 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
465 42
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
466 42
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
467 42
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
468 42
        AN(vdc->clen);
469 42
        AN(priv);
470
471 84
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC);
472 42
        if (vdps == NULL)
473 0
                return (-1);
474 42
        vdps->crc = crc32(0L, Z_NULL, 0);
475
476 42
        p = VRT_priv_task_get(ctx, chkcrc32_priv_id);
477 42
        if (p == NULL)
478 0
                return (-1);
479
480 42
        assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s));
481 42
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC);
482 42
        *priv = vdps;
483
484 42
        return (0);
485 42
}
486
487
static int v_matchproto_(vdp_init_f)
488 42
xyzzy_chklen_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
489
{
490
        struct vdp_chklen_s *vdps;
491
        struct vmod_priv *p;
492
493 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
494 42
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
495 42
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
496 42
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
497 42
        AN(vdc->clen);
498 42
        AN(priv);
499
500 84
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKLEN_MAGIC);
501 42
        if (vdps == NULL)
502 0
                return (-1);
503 42
        AZ(vdps->bytes);
504
505 42
        p = VRT_priv_task_get(ctx, chklen_priv_id);
506 42
        if (p == NULL)
507 0
                return (-1);
508
509 42
        assert(p->len == sizeof(struct vdp_chklen_cfg_s));
510 42
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKLEN_CFG_MAGIC);
511 42
        *priv = vdps;
512
513 42
        return (0);
514 42
}
515
516
static int v_matchproto_(vdp_bytes_f)
517 126
xyzzy_chksha256_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
518
    const void *ptr, ssize_t len)
519
{
520
        struct vdp_chksha256_s *vdps;
521
522 126
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
523 126
        if (len != 0)
524 63
                VSHA256_Update(vdps->cx, ptr, len);
525 126
        vdps->called++;
526 126
        vdps->bytes += len;
527 126
        return (VDP_bytes(vdc, act, ptr, len));
528
}
529
530
static int v_matchproto_(vdp_bytes_f)
531 126
xyzzy_chkcrc32_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
532
    const void *ptr, ssize_t len)
533
{
534
        struct vdp_chkcrc32_s *vdps;
535
536 126
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
537 126
        if (len > 0)
538 63
                vdps->crc = crc32(vdps->crc, ptr, len);
539 126
        vdps->called++;
540 126
        vdps->bytes += len;
541 126
        return (VDP_bytes(vdc, act, ptr, len));
542
}
543
544
static int v_matchproto_(vdp_bytes_f)
545 126
xyzzy_chklen_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
546
    const void *ptr, ssize_t len)
547
{
548
        struct vdp_chklen_s *vdps;
549
550 126
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKLEN_MAGIC);
551 126
        vdps->called++;
552 126
        vdps->bytes += len;
553 126
        return (VDP_bytes(vdc, act, ptr, len));
554
}
555
556
static int v_matchproto_(vdp_fini_f)
557 42
xyzzy_chksha256_fini(struct vdp_ctx *vdc, void **priv)
558
{
559
        unsigned char digest[VSHA256_DIGEST_LENGTH];
560
        enum vdp_chk_mode_e mode;
561
        struct vdp_chksha256_s *vdps;
562
        struct vsb *vsb;
563
        int r;
564
565 42
        (void) vdc;
566 42
        AN(priv);
567 42
        if (*priv == NULL)
568 0
                return (0);
569 42
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKSHA256_MAGIC);
570
571 42
        VSHA256_Final(digest, vdps->cx);
572 42
        r = memcmp(digest, vdps->cfg->expected, sizeof digest);
573 42
        if (r == 0)
574 21
                return (0);
575
576 21
        mode = vdps->cfg->mode;
577 21
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
578 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
579
580 21
        if (mode == VDP_CHK_LOG) {
581 21
                VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch");
582
583 21
                vsb = VSB_new_auto();
584 21
                AN(vsb);
585 21
                VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX);
586 21
                AZ(VSB_finish(vsb));
587 21
                VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb));
588
589 21
                VSB_clear(vsb);
590 21
                VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX);
591 21
                AZ(VSB_finish(vsb));
592 21
                VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb));
593 21
                VSB_destroy(&vsb);
594 21
        }
595 0
        else if (mode == VDP_CHK_PANIC)
596 0
                WRONG("body checksum");
597
        else
598 0
                WRONG("mode");
599
600 21
        return (0);
601 42
}
602
603
static int v_matchproto_(vdp_fini_f)
604 42
xyzzy_chkcrc32_fini(struct vdp_ctx *vdc, void **priv)
605
{
606
        enum vdp_chk_mode_e mode;
607
        struct vdp_chkcrc32_s *vdps;
608
609 42
        (void) vdc;
610 42
        AN(priv);
611 42
        if (*priv == NULL)
612 0
                return (0);
613 42
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKCRC32_MAGIC);
614
615 42
        if (vdps->crc == vdps->cfg->expected)
616 21
                return (0);
617
618 21
        mode = vdps->cfg->mode;
619 21
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
620 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
621
622 21
        if (mode == VDP_CHK_LOG) {
623 21
                VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch");
624 21
                VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc);
625 21
                VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected);
626 21
        }
627 0
        else if (mode == VDP_CHK_PANIC)
628 0
                WRONG("body checksum");
629
        else
630 0
                WRONG("mode");
631
632 21
        return (0);
633 42
}
634
635
static int v_matchproto_(vdp_fini_f)
636 42
xyzzy_chklen_fini(struct vdp_ctx *vdc, void **priv)
637
{
638
        enum vdp_chk_mode_e mode;
639
        struct vdp_chklen_s *vdps;
640
641 42
        (void) vdc;
642 42
        AN(priv);
643 42
        if (*priv == NULL)
644 0
                return (0);
645 42
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKLEN_MAGIC);
646
647 42
        if (vdps->bytes == vdps->cfg->expected)
648 21
                return (0);
649
650 21
        mode = vdps->cfg->mode;
651 21
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
652 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
653
654 21
        if (mode == VDP_CHK_LOG) {
655 21
                VSLb(vdc->vsl, SLT_Debug, "length mismatch");
656 21
                VSLb(vdc->vsl, SLT_Debug, "got: %zd", vdps->bytes);
657 21
                VSLb(vdc->vsl, SLT_Debug, "exp: %zd", vdps->cfg->expected);
658 21
        }
659 0
        else if (mode == VDP_CHK_PANIC)
660 0
                WRONG("body length");
661
        else
662 0
                WRONG("mode");
663
664 21
        return (0);
665 42
}
666
667
static const struct vdp xyzzy_vdp_chksha256 = {
668
        .name  = "debug.chksha256",
669
        .init  = xyzzy_chksha256_init,
670
        .bytes = xyzzy_chksha256_bytes,
671
        .fini  = xyzzy_chksha256_fini,
672
};
673
674
static const struct vdp xyzzy_vdp_chkcrc32 = {
675
        .name  = "debug.chkcrc32",
676
        .init  = xyzzy_chkcrc32_init,
677
        .bytes = xyzzy_chkcrc32_bytes,
678
        .fini  = xyzzy_chkcrc32_fini,
679
};
680
681
static const struct vdp xyzzy_vdp_chklen = {
682
        .name  = "debug.chklen",
683
        .init  = xyzzy_chklen_init,
684
        .bytes = xyzzy_chklen_bytes,
685
        .fini  = xyzzy_chklen_fini,
686
};
687
688
#define chkcfg(ws, cfg, magic, id, mode_e) do {                                                 \
689
        struct vmod_priv *p = VRT_priv_task(ctx, id);                                           \
690
                                                                                                \
691
        XXXAN(p);                                                                               \
692
        if (p->priv == NULL) {                                                                  \
693
                p->priv = WS_Alloc(ws, sizeof *cfg);                                            \
694
                p->len = sizeof *cfg;                                                           \
695
        }                                                                                       \
696
        AN(p->priv);                                                                            \
697
        cfg = p->priv;                                                                          \
698
        INIT_OBJ(cfg, magic);                                                                   \
699
        if (mode_e == VENUM(log))                                                               \
700
                cfg->mode = VDP_CHK_LOG;                                                        \
701
        else if (mode_e == VENUM(panic))                                                        \
702
                cfg->mode = VDP_CHK_PANIC;                                                      \
703
        else if (mode_e == VENUM(panic_unless_error))                                           \
704
                cfg->mode = VDP_CHK_PANIC_UNLESS_ERROR;                                         \
705
        else                                                                                    \
706
                WRONG("mode");                                                                  \
707
} while(0)
708
709
VCL_VOID v_matchproto_(td_xyzzy_debug_chksha256)
710 42
xyzzy_chksha256(VRT_CTX, VCL_BLOB blob, VCL_ENUM mode_e)
711
{
712
        struct vdp_chksha256_cfg_s *cfg;
713
        size_t l;
714
715 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
716 42
        CHECK_OBJ_NOTNULL(blob, VRT_BLOB_MAGIC);
717 42
        XXXAN(blob->blob);
718 42
        XXXAN(blob->len);
719
720 42
        chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e);
721
722 42
        l = blob->len;
723 42
        if (l > sizeof cfg->expected)
724 0
                l = sizeof cfg->expected;
725 42
        vmemcpy(cfg->expected, blob->blob, l);
726
727 42
}
728
729
VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32)
730 42
xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e)
731
{
732
        struct vdp_chkcrc32_cfg_s *cfg;
733
734 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
735
736 42
        chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e);
737
738 42
        if (expected < 0)
739 0
                expected = 0;
740 42
        cfg->expected = (uintmax_t)expected % UINT32_MAX;
741 42
}
742
743
VCL_VOID v_matchproto_(td_xyzzy_debug_chklen)
744 42
xyzzy_chklen(VRT_CTX, VCL_BYTES expected, VCL_ENUM mode_e)
745
{
746
        struct vdp_chklen_cfg_s *cfg;
747
748 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
749
750 42
        chkcfg(ctx->ws, cfg, VDP_CHKLEN_CFG_MAGIC, chklen_priv_id, mode_e);
751
752 42
        cfg->expected = expected;
753 42
}
754
755
/**********************************************************************
756
 * reserve thread_workspace
757
 */
758
759
static int v_matchproto_(vdp_init_f)
760 21
xyzzy_awshog_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
761
{
762
        struct ws *aws;
763
        unsigned u;
764
765 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
766 21
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
767 21
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
768 21
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
769 21
        AN(vdc->clen);
770 21
        AN(priv);
771
772 21
        if (ctx->req != NULL)
773 0
                aws = ctx->req->wrk->aws;
774 21
        else if (ctx->bo != NULL)
775 21
                aws = ctx->bo->wrk->aws;
776
        else
777 0
                WRONG("neither req nor bo");
778
779 21
        u = WS_ReserveAll(aws);
780 21
        WS_Release(aws, 0);
781 21
        (void) WS_Alloc(aws, u);
782 21
        return (1);
783
}
784
785
static const struct vdp xyzzy_vdp_awshog = {
786
        .name  = "debug.awshog",
787
        .init  = xyzzy_awshog_init
788
};
789
790
/**********************************************************************
791
 * send a fixed string
792
 */
793
794
static const void * const string_priv_id = &string_priv_id;
795
796
static int v_matchproto_(vdp_init_f)
797 168
xyzzy_string_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
798
{
799
        struct vmod_priv *p;
800
801 168
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
802 168
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
803 168
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
804 168
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
805 168
        AN(vdc->clen);
806
807 168
        AN(priv);
808 168
        p = VRT_priv_task_get(ctx, string_priv_id);
809 168
        if (p == NULL || p->priv == NULL) {
810 84
                *priv = TRUST_ME("");
811 84
                *vdc->clen = 0;
812 84
                return (0);
813
        }
814 84
        AN(p->priv);
815 84
        *priv = p->priv;
816 84
        *vdc->clen = vstrlen(*priv);
817 84
        return (0);
818 168
}
819
820
static int v_matchproto_(vdp_bytes_f)
821 126
xyzzy_string_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
822
    const void *ptr, ssize_t len)
823
{
824
        int r;
825
826 126
        (void)act;
827 126
        AN(priv);
828 126
        (void)ptr;
829 126
        (void)len;
830
831 126
        r = VDP_bytes(vdc, VDP_END, *priv, vstrlen(*priv));
832 126
        if (r != 0)
833 0
                return (r);
834
        // only to be called once
835 126
        return (1);
836 126
}
837
838
static int v_matchproto_(vdp_fini_f)
839 168
xyzzy_string_fini(struct vdp_ctx *vdc, void **priv)
840
{
841 168
        (void)vdc;
842 168
        AN(priv);
843 168
        *priv = NULL;
844 168
        return (0);
845
}
846
847
static const struct vdp xyzzy_vdp_string = {
848
        .name  = "debug.string",
849
        .init  = xyzzy_string_init,
850
        .bytes = xyzzy_string_bytes,
851
        .fini = xyzzy_string_fini,
852
};
853
854
VCL_VOID v_matchproto_(td_xyzzy_debug_body_string)
855 84
xyzzy_body_string(VRT_CTX, VCL_STRING s)
856
{
857
        struct vmod_priv *p;
858
859 84
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
860 84
        p = VRT_priv_task(ctx, string_priv_id);
861 84
        if (p == NULL)
862 0
                return;
863 84
        p->priv = TRUST_ME(s);
864 84
}
865
866
/**********************************************************************/
867
868
static int v_matchproto_(vdp_init_f)
869 42
xyzzy_vdp_body_prefix_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
870
{
871
        struct xyzzy_bp_string *bps;
872
        struct xyzzy_bp *bp;
873
        struct vmod_priv *task;
874
        intmax_t l;
875
876 42
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
877 42
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
878 42
        AN(vdc->clen);
879
880 42
        task = VRT_priv_task_get(ctx, priv_task_id_bp);
881 42
        if (task == NULL)
882 0
                return (1);
883 42
        CAST_OBJ_NOTNULL(bp, task->priv, XYZZY_BP_MAGIC);
884 42
        AN(priv);
885 42
        AZ(*priv);
886 42
        *priv = bp;
887
888 42
        if (*vdc->clen < 0)
889 0
                return (0);
890
891 42
        l = 0;
892 126
        VSTAILQ_FOREACH(bps, &bp->head, list)
893 84
                l += vstrlen(bps->s);
894 42
        *vdc->clen += l;
895
896 42
        return (0);
897 42
}
898
899
static int v_matchproto_(vdp_bytes_f)
900 84
xyzzy_vdp_body_prefix_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
901
    const void *ptr, ssize_t len)
902
{
903
        struct xyzzy_bp_string *bps;
904
        struct xyzzy_bp *bp;
905
906 84
        AN(priv);
907 84
        CAST_OBJ_NOTNULL(bp, *priv, XYZZY_BP_MAGIC);
908
909 168
        while ((bps = VSTAILQ_FIRST(&bp->head)) != NULL) {
910 84
                VSTAILQ_REMOVE_HEAD(&bp->head, list);
911 84
                if (VDP_bytes(vdc, VDP_NULL, bps->s, vstrlen(bps->s)))
912 0
                        return (vdc->retval);
913
        }
914
915 84
        return (VDP_bytes(vdc, act, ptr, len));
916 84
}
917
918
static int v_matchproto_(vdp_fini_f)
919 42
xyzzy_vdp_body_prefix_fini(struct vdp_ctx *vdc, void **priv)
920
{
921 42
        (void)vdc;
922 42
        AN(priv);
923 42
        *priv = NULL;
924 42
        return (0);
925
}
926
927
static const struct vdp xyzzy_vdp_body_prefix = {
928
        .name  = "debug.body_prefix",
929
        .init  = xyzzy_vdp_body_prefix_init,
930
        .bytes = xyzzy_vdp_body_prefix_bytes,
931
        .fini = xyzzy_vdp_body_prefix_fini
932
};
933
934
void
935 2205
debug_add_filters(VRT_CTX)
936
{
937 2205
        AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow));
938 2205
        AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
939 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic));
940 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked));
941 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256));
942 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32));
943 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chklen));
944 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_awshog));
945 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_string));
946 2205
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_body_prefix));
947 2205
}
948
949
void
950 483
debug_remove_filters(VRT_CTX)
951
{
952 483
        VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow);
953 483
        VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13);
954 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic);
955 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked);
956 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256);
957 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32);
958 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chklen);
959 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_awshog);
960 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_string);
961 483
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_body_prefix);
962 483
}