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 117
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 117
        (void)vfe;
59 117
        vp = VFP_Suck(vc, p, lp);
60 117
        if (vp == VFP_ERROR)
61 0
                return (vp);
62 117
        q = p;
63 3393
        for (l = 0; l < *lp; l++, q++) {
64 3276
                if (*q >= 'A' && *q <= 'Z')
65 468
                        *q = (((*q - 'A') + 13) % 26) + 'A';
66 3276
                if (*q >= 'a' && *q <= 'z')
67 2223
                        *q = (((*q - 'a') + 13) % 26) + 'a';
68 3276
        }
69 117
        return (vp);
70 117
}
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 299
xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
84
{
85
86 299
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
87 299
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
88 299
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
89 299
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
90 299
        AN(vdc->clen);
91
92 299
        AN(priv);
93
94 299
        *priv = malloc(ROT13_BUFSZ);
95 299
        if (*priv == NULL)
96 0
                return (-1);
97
98 299
        return (0);
99 299
}
100
101
static int v_matchproto_(vdp_bytes_f)
102 468
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 468
        int i, j, retval = 0;
108
109 468
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
110 468
        AN(priv);
111 468
        AN(*priv);
112 468
        if (len <= 0)
113 78
                return (VDP_bytes(vdc, act, ptr, len));
114 390
        AN(ptr);
115 390
        if (act != VDP_END)
116 130
                act = VDP_FLUSH;
117 390
        q = *priv;
118 390
        pp = ptr;
119
120 1370798
        for (i = 0, j = 0; j < len; i++, j++) {
121 1370408
                if (pp[j] >= 'A' && pp[j] <= 'Z')
122 368186
                        q[i] = (((pp[j] - 'A') + 13) % 26) + 'A';
123 1002222
                else if (pp[j] >= 'a' && pp[j] <= 'z')
124 372600
                        q[i] = (((pp[j] - 'a') + 13) % 26) + 'a';
125
                else
126 629622
                        q[i] = pp[j];
127 1370408
                if (i == ROT13_BUFSZ - 1 && j < len - 1) {
128 171106
                        retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ);
129 171106
                        if (retval != 0)
130 0
                                return (retval);
131 171106
                        i = -1;
132 171106
                }
133 1370408
        }
134 390
        if (i >= 0)
135 390
                retval = VDP_bytes(vdc, act, q, i);
136 390
        return (retval);
137 468
}
138
139
static int v_matchproto_(vdp_fini_f)
140 299
xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv)
141
{
142 299
        (void)vdc;
143 299
        AN(priv);
144 299
        free(*priv);
145 299
        *priv = NULL;
146 299
        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 13
xyzzy_rot104(VRT_CTX)
158
{
159
160 13
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
161
        // This should fail
162 13
        AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
163 13
}
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 351
xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
175
{
176
177 351
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
178 351
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
179 351
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
180 351
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
181 351
        AN(vdc->clen);
182 351
        AN(priv);
183
184 351
        http_Unset(vdc->hp, H_Content_Length);
185 351
        *vdc->clen = -1;
186
187 351
        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 2469
priv_pedantic_fini(VRT_CTX, void *priv)
221
{
222
        struct vdp_state_s *vdps;
223
224 2469
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
225 2469
        CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
226
227 2469
        assert(vdps->state == VDPS_FINI);
228 2469
}
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 2574
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 2574
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
243 2574
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
244 2574
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
245 2574
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
246 2574
        AN(vdc->clen);
247 2574
        AN(priv);
248
249 5044
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC);
250 2574
        if (vdps == NULL)
251 104
                return (-1);
252 2470
        assert(vdps->state == VDPS_NULL);
253
254 2470
        p = VRT_priv_task(ctx, (void *)vdc);
255 2470
        if (p == NULL)
256 0
                return (-1);
257 2470
        p->priv = vdps;
258 2470
        p->methods = priv_pedantic_methods;
259
260 2470
        *priv = vdps;
261
262 2470
        vdps->state = VDPS_INIT;
263
264 2470
        return (0);
265 2574
}
266
267
static int v_matchproto_(vdp_bytes_f)
268 3103
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 3103
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
274 3103
        assert(vdps->state >= VDPS_INIT);
275 3103
        assert(vdps->state < VDPS_END);
276
277 3103
        if (act == VDP_END)
278 806
                vdps->state = VDPS_END;
279
        else
280 2297
                vdps->state = VDPS_BYTES;
281
282 3103
        return (VDP_bytes(vdc, act, ptr, len));
283
}
284
285
static int v_matchproto_(vdp_fini_f)
286 2574
xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv)
287
{
288
        struct vdp_state_s *vdps;
289
290 2574
        (void) vdc;
291 2574
        AN(priv);
292 2574
        if (*priv == NULL)
293 104
                return (0);
294 2470
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
295 2470
        assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END);
296 2470
        vdps->state = VDPS_FINI;
297
298 2470
        return (0);
299 2574
}
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 52
xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
335
    const void *ptr, ssize_t len)
336
{
337
338 52
        (void)priv;
339 52
        VTIM_sleep(1.0);
340 52
        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
 * check VDPs:
350
 *
351
 * test that the stream of bytes has a certain checksum or length and either log
352
 * or panic
353
 *
354
 * The sha256 and crc32 variants are basically identical, but the amount of
355
 * code does not justify generalizing. (slink)
356
 */
357
358
enum vdp_chk_mode_e {
359
        //lint -esym(749, vdp_chk_mode_e::VDP_CHK_INVAL) deliberately not referenced
360
        VDP_CHK_INVAL = 0,
361
        VDP_CHK_LOG,
362
        VDP_CHK_PANIC,
363
        VDP_CHK_PANIC_UNLESS_ERROR
364
};
365
366
struct vdp_chksha256_cfg_s {
367
        unsigned                        magic;
368
#define VDP_CHKSHA256_CFG_MAGIC         0x624f5b32
369
        enum vdp_chk_mode_e             mode;
370
        unsigned char                   expected[VSHA256_DIGEST_LENGTH];
371
};
372
373
struct vdp_chkcrc32_cfg_s {
374
        unsigned                        magic;
375
#define VDP_CHKCRC32_CFG_MAGIC          0x5a7a835c
376
        enum vdp_chk_mode_e             mode;
377
        uint32_t                        expected;
378
};
379
380
struct vdp_chklen_cfg_s {
381
        unsigned                        magic;
382
#define VDP_CHKLEN_CFG_MAGIC            0x08cf3426
383
        enum vdp_chk_mode_e             mode;
384
        size_t                          expected;
385
};
386
387
struct vdp_chksha256_s {
388
        unsigned                        magic;
389
#define VDP_CHKSHA256_MAGIC             0x6856e913
390
        unsigned                        called;
391
        size_t                          bytes;
392
        struct VSHA256Context           cx[1];
393
        struct vdp_chksha256_cfg_s      *cfg;
394
};
395
396
struct vdp_chkcrc32_s {
397
        unsigned                        magic;
398
#define VDP_CHKCRC32_MAGIC              0x15c03d3c
399
        unsigned                        called;
400
        size_t                          bytes;
401
        uint32_t                        crc;
402
        struct vdp_chkcrc32_cfg_s       *cfg;
403
};
404
405
struct vdp_chklen_s {
406
        unsigned                        magic;
407
#define VDP_CHKLEN_MAGIC                0x029811f5
408
        unsigned                        called;
409
        size_t                          bytes;
410
        struct vdp_chklen_cfg_s         *cfg;
411
};
412
413
static const void * const chksha256_priv_id = &chksha256_priv_id;
414
static const void * const chkcrc32_priv_id = &chkcrc32_priv_id;
415
static const void * const chklen_priv_id = &chklen_priv_id;
416
417
static int v_matchproto_(vdp_init_f)
418 26
xyzzy_chksha256_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
419
{
420
        struct vdp_chksha256_s *vdps;
421
        struct vmod_priv *p;
422
423 26
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
424 26
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
425 26
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
426 26
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
427 26
        AN(vdc->clen);
428 26
        AN(priv);
429
430 52
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC);
431 26
        if (vdps == NULL)
432 0
                return (-1);
433 26
        VSHA256_Init(vdps->cx);
434
435 26
        p = VRT_priv_task_get(ctx, chksha256_priv_id);
436 26
        if (p == NULL)
437 0
                return (-1);
438
439 26
        assert(p->len == sizeof(struct vdp_chksha256_cfg_s));
440 26
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC);
441 26
        *priv = vdps;
442
443 26
        return (0);
444 26
}
445
446
static int v_matchproto_(vdp_init_f)
447 26
xyzzy_chkcrc32_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
448
{
449
        struct vdp_chkcrc32_s *vdps;
450
        struct vmod_priv *p;
451
452 26
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
453 26
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
454 26
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
455 26
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
456 26
        AN(vdc->clen);
457 26
        AN(priv);
458
459 52
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC);
460 26
        if (vdps == NULL)
461 0
                return (-1);
462 26
        vdps->crc = crc32(0L, Z_NULL, 0);
463
464 26
        p = VRT_priv_task_get(ctx, chkcrc32_priv_id);
465 26
        if (p == NULL)
466 0
                return (-1);
467
468 26
        assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s));
469 26
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC);
470 26
        *priv = vdps;
471
472 26
        return (0);
473 26
}
474
475
static int v_matchproto_(vdp_init_f)
476 26
xyzzy_chklen_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
477
{
478
        struct vdp_chklen_s *vdps;
479
        struct vmod_priv *p;
480
481 26
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
482 26
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
483 26
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
484 26
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
485 26
        AN(vdc->clen);
486 26
        AN(priv);
487
488 52
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKLEN_MAGIC);
489 26
        if (vdps == NULL)
490 0
                return (-1);
491 26
        AZ(vdps->bytes);
492
493 26
        p = VRT_priv_task_get(ctx, chklen_priv_id);
494 26
        if (p == NULL)
495 0
                return (-1);
496
497 26
        assert(p->len == sizeof(struct vdp_chklen_cfg_s));
498 26
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKLEN_CFG_MAGIC);
499 26
        *priv = vdps;
500
501 26
        return (0);
502 26
}
503
504
static int v_matchproto_(vdp_bytes_f)
505 78
xyzzy_chksha256_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
506
    const void *ptr, ssize_t len)
507
{
508
        struct vdp_chksha256_s *vdps;
509
510 78
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
511 78
        if (len != 0)
512 39
                VSHA256_Update(vdps->cx, ptr, len);
513 78
        vdps->called++;
514 78
        vdps->bytes += len;
515 78
        return (VDP_bytes(vdc, act, ptr, len));
516
}
517
518
static int v_matchproto_(vdp_bytes_f)
519 78
xyzzy_chkcrc32_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
520
    const void *ptr, ssize_t len)
521
{
522
        struct vdp_chkcrc32_s *vdps;
523
524 78
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
525 78
        if (len > 0)
526 39
                vdps->crc = crc32(vdps->crc, ptr, len);
527 78
        vdps->called++;
528 78
        vdps->bytes += len;
529 78
        return (VDP_bytes(vdc, act, ptr, len));
530
}
531
532
static int v_matchproto_(vdp_bytes_f)
533 78
xyzzy_chklen_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
534
    const void *ptr, ssize_t len)
535
{
536
        struct vdp_chklen_s *vdps;
537
538 78
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKLEN_MAGIC);
539 78
        vdps->called++;
540 78
        vdps->bytes += len;
541 78
        return (VDP_bytes(vdc, act, ptr, len));
542
}
543
544
static int v_matchproto_(vdp_fini_f)
545 26
xyzzy_chksha256_fini(struct vdp_ctx *vdc, void **priv)
546
{
547
        unsigned char digest[VSHA256_DIGEST_LENGTH];
548
        enum vdp_chk_mode_e mode;
549
        struct vdp_chksha256_s *vdps;
550
        struct vsb *vsb;
551
        int r;
552
553 26
        (void) vdc;
554 26
        AN(priv);
555 26
        if (*priv == NULL)
556 0
                return (0);
557 26
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKSHA256_MAGIC);
558
559 26
        VSHA256_Final(digest, vdps->cx);
560 26
        r = memcmp(digest, vdps->cfg->expected, sizeof digest);
561 26
        if (r == 0)
562 13
                return (0);
563
564 13
        mode = vdps->cfg->mode;
565 13
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
566 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
567
568 13
        if (mode == VDP_CHK_LOG) {
569 13
                VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch");
570
571 13
                vsb = VSB_new_auto();
572 13
                AN(vsb);
573 13
                VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX);
574 13
                AZ(VSB_finish(vsb));
575 13
                VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb));
576
577 13
                VSB_clear(vsb);
578 13
                VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX);
579 13
                AZ(VSB_finish(vsb));
580 13
                VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb));
581 13
                VSB_destroy(&vsb);
582 13
        }
583 0
        else if (mode == VDP_CHK_PANIC)
584 0
                WRONG("body checksum");
585
        else
586 0
                WRONG("mode");
587
588 13
        return (0);
589 26
}
590
591
static int v_matchproto_(vdp_fini_f)
592 26
xyzzy_chkcrc32_fini(struct vdp_ctx *vdc, void **priv)
593
{
594
        enum vdp_chk_mode_e mode;
595
        struct vdp_chkcrc32_s *vdps;
596
597 26
        (void) vdc;
598 26
        AN(priv);
599 26
        if (*priv == NULL)
600 0
                return (0);
601 26
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKCRC32_MAGIC);
602
603 26
        if (vdps->crc == vdps->cfg->expected)
604 13
                return (0);
605
606 13
        mode = vdps->cfg->mode;
607 13
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
608 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
609
610 13
        if (mode == VDP_CHK_LOG) {
611 13
                VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch");
612 13
                VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc);
613 13
                VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected);
614 13
        }
615 0
        else if (mode == VDP_CHK_PANIC)
616 0
                WRONG("body checksum");
617
        else
618 0
                WRONG("mode");
619
620 13
        return (0);
621 26
}
622
623
static int v_matchproto_(vdp_fini_f)
624 26
xyzzy_chklen_fini(struct vdp_ctx *vdc, void **priv)
625
{
626
        enum vdp_chk_mode_e mode;
627
        struct vdp_chklen_s *vdps;
628
629 26
        (void) vdc;
630 26
        AN(priv);
631 26
        if (*priv == NULL)
632 0
                return (0);
633 26
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKLEN_MAGIC);
634
635 26
        if (vdps->bytes == vdps->cfg->expected)
636 13
                return (0);
637
638 13
        mode = vdps->cfg->mode;
639 13
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
640 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
641
642 13
        if (mode == VDP_CHK_LOG) {
643 13
                VSLb(vdc->vsl, SLT_Debug, "length mismatch");
644 13
                VSLb(vdc->vsl, SLT_Debug, "got: %zd", vdps->bytes);
645 13
                VSLb(vdc->vsl, SLT_Debug, "exp: %zd", vdps->cfg->expected);
646 13
        }
647 0
        else if (mode == VDP_CHK_PANIC)
648 0
                WRONG("body length");
649
        else
650 0
                WRONG("mode");
651
652 13
        return (0);
653 26
}
654
655
static const struct vdp xyzzy_vdp_chksha256 = {
656
        .name  = "debug.chksha256",
657
        .init  = xyzzy_chksha256_init,
658
        .bytes = xyzzy_chksha256_bytes,
659
        .fini  = xyzzy_chksha256_fini,
660
};
661
662
static const struct vdp xyzzy_vdp_chkcrc32 = {
663
        .name  = "debug.chkcrc32",
664
        .init  = xyzzy_chkcrc32_init,
665
        .bytes = xyzzy_chkcrc32_bytes,
666
        .fini  = xyzzy_chkcrc32_fini,
667
};
668
669
static const struct vdp xyzzy_vdp_chklen = {
670
        .name  = "debug.chklen",
671
        .init  = xyzzy_chklen_init,
672
        .bytes = xyzzy_chklen_bytes,
673
        .fini  = xyzzy_chklen_fini,
674
};
675
676
#define chkcfg(ws, cfg, magic, id, mode_e) do {                                                 \
677
        struct vmod_priv *p = VRT_priv_task(ctx, id);                                           \
678
                                                                                                \
679
        XXXAN(p);                                                                               \
680
        if (p->priv == NULL) {                                                                  \
681
                p->priv = WS_Alloc(ws, sizeof *cfg);                                            \
682
                p->len = sizeof *cfg;                                                           \
683
        }                                                                                       \
684
        AN(p->priv);                                                                            \
685
        cfg = p->priv;                                                                          \
686
        INIT_OBJ(cfg, magic);                                                                   \
687
        if (mode_e == VENUM(log))                                                               \
688
                cfg->mode = VDP_CHK_LOG;                                                        \
689
        else if (mode_e == VENUM(panic))                                                        \
690
                cfg->mode = VDP_CHK_PANIC;                                                      \
691
        else if (mode_e == VENUM(panic_unless_error))                                           \
692
                cfg->mode = VDP_CHK_PANIC_UNLESS_ERROR;                                         \
693
        else                                                                                    \
694
                WRONG("mode");                                                                  \
695
} while(0)
696
697
VCL_VOID v_matchproto_(td_xyzzy_debug_chksha256)
698 26
xyzzy_chksha256(VRT_CTX, VCL_BLOB blob, VCL_ENUM mode_e)
699
{
700
        struct vdp_chksha256_cfg_s *cfg;
701
        size_t l;
702
703 26
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
704 26
        CHECK_OBJ_NOTNULL(blob, VRT_BLOB_MAGIC);
705 26
        XXXAN(blob->blob);
706 26
        XXXAN(blob->len);
707
708 26
        chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e);
709
710 26
        l = blob->len;
711 26
        if (l > sizeof cfg->expected)
712 0
                l = sizeof cfg->expected;
713 26
        memcpy(cfg->expected, blob->blob, l);
714
715 26
}
716
717
VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32)
718 26
xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e)
719
{
720
        struct vdp_chkcrc32_cfg_s *cfg;
721
722 26
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
723
724 26
        chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e);
725
726 26
        if (expected < 0)
727 0
                expected = 0;
728 26
        cfg->expected = (uintmax_t)expected % UINT32_MAX;
729 26
}
730
731
VCL_VOID v_matchproto_(td_xyzzy_debug_chklen)
732 26
xyzzy_chklen(VRT_CTX, VCL_BYTES expected, VCL_ENUM mode_e)
733
{
734
        struct vdp_chklen_cfg_s *cfg;
735
736 26
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
737
738 26
        chkcfg(ctx->ws, cfg, VDP_CHKLEN_CFG_MAGIC, chklen_priv_id, mode_e);
739
740 26
        cfg->expected = expected;
741 26
}
742
743
/**********************************************************************
744
 * reserve thread_workspace
745
 */
746
747
static int v_matchproto_(vdp_init_f)
748 13
xyzzy_awshog_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
749
{
750
        struct ws *aws;
751
        unsigned u;
752
753 13
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
754 13
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
755 13
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
756 13
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
757 13
        AN(vdc->clen);
758 13
        AN(priv);
759
760 13
        if (ctx->req != NULL)
761 0
                aws = ctx->req->wrk->aws;
762 13
        else if (ctx->bo != NULL)
763 13
                aws = ctx->bo->wrk->aws;
764
        else
765 0
                WRONG("neither req nor bo");
766
767 13
        u = WS_ReserveAll(aws);
768 13
        WS_Release(aws, 0);
769 13
        (void) WS_Alloc(aws, u);
770 13
        return (1);
771
}
772
773
static const struct vdp xyzzy_vdp_awshog = {
774
        .name  = "debug.awshog",
775
        .init  = xyzzy_awshog_init
776
};
777
778
void
779 1339
debug_add_filters(VRT_CTX)
780
{
781 1339
        AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
782 1339
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic));
783 1339
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked));
784 1339
        AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow));
785 1339
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256));
786 1339
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32));
787 1339
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chklen));
788 1339
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_awshog));
789 1339
}
790
791
void
792 299
debug_remove_filters(VRT_CTX)
793
{
794 299
        VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow);
795 299
        VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13);
796 299
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic);
797 299
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked);
798 299
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256);
799 299
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32);
800 299
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chklen);
801 299
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_awshog);
802 299
}