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 36
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 36
        (void)vfe;
59 36
        vp = VFP_Suck(vc, p, lp);
60 36
        if (vp == VFP_ERROR)
61 0
                return (vp);
62 36
        q = p;
63 1044
        for (l = 0; l < *lp; l++, q++) {
64 1008
                if (*q >= 'A' && *q <= 'Z')
65 144
                        *q = (((*q - 'A') + 13) % 26) + 'A';
66 1008
                if (*q >= 'a' && *q <= 'z')
67 684
                        *q = (((*q - 'a') + 13) % 26) + 'a';
68 1008
        }
69 36
        return (vp);
70 36
}
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 8
xyzzy_rot13_fail_init(VRT_CTX)
86
{
87
88 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
89 8
        rot13_init_fail = 1;
90 8
}
91
92
static int v_matchproto_(vdp_init_f)
93 108
xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
94
{
95
96 108
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
97 108
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
98 108
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
99 108
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
100 108
        AN(vdc->clen);
101
102 108
        AN(priv);
103
104 108
        if (rot13_init_fail)
105 8
                return (-1);
106 100
        *priv = malloc(ROT13_BUFSZ);
107 100
        if (*priv == NULL)
108 0
                return (-1);
109
110 100
        return (0);
111 108
}
112
113
static int v_matchproto_(vdp_bytes_f)
114 152
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 152
        int i, j, retval = 0;
120
121 152
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
122 152
        AN(priv);
123 152
        AN(*priv);
124 152
        if (len <= 0)
125 24
                return (VDP_bytes(vdc, act, ptr, len));
126 128
        AN(ptr);
127 128
        if (act != VDP_END)
128 40
                act = VDP_FLUSH;
129 128
        q = *priv;
130 128
        pp = ptr;
131
132 422016
        for (i = 0, j = 0; j < len; i++, j++) {
133 421888
                if (pp[j] >= 'A' && pp[j] <= 'Z')
134 113416
                        q[i] = (((pp[j] - 'A') + 13) % 26) + 'A';
135 308472
                else if (pp[j] >= 'a' && pp[j] <= 'z')
136 114560
                        q[i] = (((pp[j] - 'a') + 13) % 26) + 'a';
137
                else
138 193912
                        q[i] = pp[j];
139 421888
                if (i == ROT13_BUFSZ - 1 && j < len - 1) {
140 52672
                        retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ);
141 52672
                        if (retval != 0)
142 0
                                return (retval);
143 52672
                        i = -1;
144 52672
                }
145 421888
        }
146 128
        if (i >= 0)
147 128
                retval = VDP_bytes(vdc, act, q, i);
148 128
        return (retval);
149 152
}
150
151
static int v_matchproto_(vdp_fini_f)
152 100
xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv)
153
{
154 100
        (void)vdc;
155 100
        AN(priv);
156 100
        AN(*priv);
157 100
        free(*priv);
158 100
        *priv = NULL;
159 100
        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 4
xyzzy_rot104(VRT_CTX)
171
{
172
173 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
174
        // This should fail
175 4
        AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
176 4
}
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 128
xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
188
{
189
190 128
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
191 128
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
192 128
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
193 128
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
194 128
        AN(vdc->clen);
195 128
        AN(priv);
196
197 128
        *vdc->clen = -1;
198
199 128
        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 800
priv_pedantic_fini(VRT_CTX, void *priv)
233
{
234
        struct vdp_state_s *vdps;
235
236 800
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
237 800
        CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
238
239 800
        assert(vdps->state == VDPS_FINI);
240 800
}
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 832
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 832
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
255 832
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
256 832
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
257 832
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
258 832
        AN(vdc->clen);
259 832
        AN(priv);
260
261 1632
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC);
262 832
        if (vdps == NULL)
263 32
                return (-1);
264 800
        assert(vdps->state == VDPS_NULL);
265
266 800
        p = VRT_priv_task(ctx, (void *)vdc);
267 800
        if (p == NULL)
268 0
                return (-1);
269 800
        p->priv = vdps;
270 800
        p->methods = priv_pedantic_methods;
271
272 800
        *priv = vdps;
273
274 800
        vdps->state = VDPS_INIT;
275
276 800
        return (0);
277 832
}
278
279
static int v_matchproto_(vdp_bytes_f)
280 1012
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 1012
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC);
286 1012
        assert(vdps->state >= VDPS_INIT);
287 1012
        assert(vdps->state < VDPS_END);
288
289 1012
        if (act == VDP_END)
290 280
                vdps->state = VDPS_END;
291
        else
292 732
                vdps->state = VDPS_BYTES;
293
294 1012
        return (VDP_bytes(vdc, act, ptr, len));
295
}
296
297
static int v_matchproto_(vdp_fini_f)
298 800
xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv)
299
{
300
        struct vdp_state_s *vdps;
301
302 800
        (void) vdc;
303 800
        AN(priv);
304 800
        if (*priv == NULL)
305 0
                return (0);
306 800
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC);
307 800
        assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END);
308 800
        vdps->state = VDPS_FINI;
309
310 800
        return (0);
311 800
}
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 16
xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
347
    const void *ptr, ssize_t len)
348
{
349
350 16
        (void)priv;
351 16
        VTIM_sleep(1.0);
352 16
        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 8
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 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
436 8
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
437 8
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
438 8
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
439 8
        AN(vdc->clen);
440 8
        AN(priv);
441
442 16
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC);
443 8
        if (vdps == NULL)
444 0
                return (-1);
445 8
        VSHA256_Init(vdps->cx);
446
447 8
        p = VRT_priv_task_get(ctx, chksha256_priv_id);
448 8
        if (p == NULL)
449 0
                return (-1);
450
451 8
        assert(p->len == sizeof(struct vdp_chksha256_cfg_s));
452 8
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC);
453 8
        *priv = vdps;
454
455 8
        return (0);
456 8
}
457
458
static int v_matchproto_(vdp_init_f)
459 8
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 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
465 8
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
466 8
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
467 8
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
468 8
        AN(vdc->clen);
469 8
        AN(priv);
470
471 16
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC);
472 8
        if (vdps == NULL)
473 0
                return (-1);
474 8
        vdps->crc = crc32(0L, Z_NULL, 0);
475
476 8
        p = VRT_priv_task_get(ctx, chkcrc32_priv_id);
477 8
        if (p == NULL)
478 0
                return (-1);
479
480 8
        assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s));
481 8
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC);
482 8
        *priv = vdps;
483
484 8
        return (0);
485 8
}
486
487
static int v_matchproto_(vdp_init_f)
488 8
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 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
494 8
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
495 8
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
496 8
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
497 8
        AN(vdc->clen);
498 8
        AN(priv);
499
500 16
        WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKLEN_MAGIC);
501 8
        if (vdps == NULL)
502 0
                return (-1);
503 8
        AZ(vdps->bytes);
504
505 8
        p = VRT_priv_task_get(ctx, chklen_priv_id);
506 8
        if (p == NULL)
507 0
                return (-1);
508
509 8
        assert(p->len == sizeof(struct vdp_chklen_cfg_s));
510 8
        CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKLEN_CFG_MAGIC);
511 8
        *priv = vdps;
512
513 8
        return (0);
514 8
}
515
516
static int v_matchproto_(vdp_bytes_f)
517 24
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 24
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC);
523 24
        if (len != 0)
524 12
                VSHA256_Update(vdps->cx, ptr, len);
525 24
        vdps->called++;
526 24
        vdps->bytes += len;
527 24
        return (VDP_bytes(vdc, act, ptr, len));
528
}
529
530
static int v_matchproto_(vdp_bytes_f)
531 24
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 24
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC);
537 24
        if (len > 0)
538 12
                vdps->crc = crc32(vdps->crc, ptr, len);
539 24
        vdps->called++;
540 24
        vdps->bytes += len;
541 24
        return (VDP_bytes(vdc, act, ptr, len));
542
}
543
544
static int v_matchproto_(vdp_bytes_f)
545 24
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 24
        CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKLEN_MAGIC);
551 24
        vdps->called++;
552 24
        vdps->bytes += len;
553 24
        return (VDP_bytes(vdc, act, ptr, len));
554
}
555
556
static int v_matchproto_(vdp_fini_f)
557 8
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 8
        (void) vdc;
566 8
        AN(priv);
567 8
        if (*priv == NULL)
568 0
                return (0);
569 8
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKSHA256_MAGIC);
570
571 8
        VSHA256_Final(digest, vdps->cx);
572 8
        r = memcmp(digest, vdps->cfg->expected, sizeof digest);
573 8
        if (r == 0)
574 4
                return (0);
575
576 4
        mode = vdps->cfg->mode;
577 4
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
578 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
579
580 4
        if (mode == VDP_CHK_LOG) {
581 4
                VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch");
582
583 4
                vsb = VSB_new_auto();
584 4
                AN(vsb);
585 4
                VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX);
586 4
                AZ(VSB_finish(vsb));
587 4
                VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb));
588
589 4
                VSB_clear(vsb);
590 4
                VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX);
591 4
                AZ(VSB_finish(vsb));
592 4
                VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb));
593 4
                VSB_destroy(&vsb);
594 4
        }
595 0
        else if (mode == VDP_CHK_PANIC)
596 0
                WRONG("body checksum");
597
        else
598 0
                WRONG("mode");
599
600 4
        return (0);
601 8
}
602
603
static int v_matchproto_(vdp_fini_f)
604 8
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 8
        (void) vdc;
610 8
        AN(priv);
611 8
        if (*priv == NULL)
612 0
                return (0);
613 8
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKCRC32_MAGIC);
614
615 8
        if (vdps->crc == vdps->cfg->expected)
616 4
                return (0);
617
618 4
        mode = vdps->cfg->mode;
619 4
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
620 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
621
622 4
        if (mode == VDP_CHK_LOG) {
623 4
                VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch");
624 4
                VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc);
625 4
                VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected);
626 4
        }
627 0
        else if (mode == VDP_CHK_PANIC)
628 0
                WRONG("body checksum");
629
        else
630 0
                WRONG("mode");
631
632 4
        return (0);
633 8
}
634
635
static int v_matchproto_(vdp_fini_f)
636 8
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 8
        (void) vdc;
642 8
        AN(priv);
643 8
        if (*priv == NULL)
644 0
                return (0);
645 8
        TAKE_OBJ_NOTNULL(vdps, priv, VDP_CHKLEN_MAGIC);
646
647 8
        if (vdps->bytes == vdps->cfg->expected)
648 4
                return (0);
649
650 4
        mode = vdps->cfg->mode;
651 4
        if (mode == VDP_CHK_PANIC_UNLESS_ERROR)
652 0
                mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC;
653
654 4
        if (mode == VDP_CHK_LOG) {
655 4
                VSLb(vdc->vsl, SLT_Debug, "length mismatch");
656 4
                VSLb(vdc->vsl, SLT_Debug, "got: %zd", vdps->bytes);
657 4
                VSLb(vdc->vsl, SLT_Debug, "exp: %zd", vdps->cfg->expected);
658 4
        }
659 0
        else if (mode == VDP_CHK_PANIC)
660 0
                WRONG("body length");
661
        else
662 0
                WRONG("mode");
663
664 4
        return (0);
665 8
}
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 8
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 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
716 8
        CHECK_OBJ_NOTNULL(blob, VRT_BLOB_MAGIC);
717 8
        XXXAN(blob->blob);
718 8
        XXXAN(blob->len);
719
720 8
        chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e);
721
722 8
        l = blob->len;
723 8
        if (l > sizeof cfg->expected)
724 0
                l = sizeof cfg->expected;
725 8
        vmemcpy(cfg->expected, blob->blob, l);
726
727 8
}
728
729
VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32)
730 8
xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e)
731
{
732
        struct vdp_chkcrc32_cfg_s *cfg;
733
734 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
735
736 8
        chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e);
737
738 8
        if (expected < 0)
739 0
                expected = 0;
740 8
        cfg->expected = (uintmax_t)expected % UINT32_MAX;
741 8
}
742
743
VCL_VOID v_matchproto_(td_xyzzy_debug_chklen)
744 8
xyzzy_chklen(VRT_CTX, VCL_BYTES expected, VCL_ENUM mode_e)
745
{
746
        struct vdp_chklen_cfg_s *cfg;
747
748 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
749
750 8
        chkcfg(ctx->ws, cfg, VDP_CHKLEN_CFG_MAGIC, chklen_priv_id, mode_e);
751
752 8
        cfg->expected = expected;
753 8
}
754
755
/**********************************************************************
756
 * reserve thread_workspace
757
 */
758
759
static int v_matchproto_(vdp_init_f)
760 4
xyzzy_awshog_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
761
{
762
        struct ws *aws;
763
        unsigned u;
764
765 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
766 4
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
767 4
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
768 4
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
769 4
        AN(vdc->clen);
770 4
        AN(priv);
771
772 4
        if (ctx->req != NULL)
773 0
                aws = ctx->req->wrk->aws;
774 4
        else if (ctx->bo != NULL)
775 4
                aws = ctx->bo->wrk->aws;
776
        else
777 0
                WRONG("neither req nor bo");
778
779 4
        u = WS_ReserveAll(aws);
780 4
        WS_Release(aws, 0);
781 4
        (void) WS_Alloc(aws, u);
782 4
        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 32
xyzzy_string_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
798
{
799
        struct vmod_priv *p;
800
801 32
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
802 32
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
803 32
        CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC);
804 32
        CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC);
805 32
        AN(vdc->clen);
806
807 32
        AN(priv);
808 32
        p = VRT_priv_task_get(ctx, string_priv_id);
809 32
        if (p == NULL || p->priv == NULL) {
810 16
                *priv = TRUST_ME("");
811 16
                *vdc->clen = 0;
812 16
                return (0);
813
        }
814 16
        AN(p->priv);
815 16
        *priv = p->priv;
816 16
        *vdc->clen = vstrlen(*priv);
817 16
        return (0);
818 32
}
819
820
static int v_matchproto_(vdp_bytes_f)
821 24
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 24
        (void)act;
827 24
        AN(priv);
828 24
        (void)ptr;
829 24
        (void)len;
830
831 24
        r = VDP_bytes(vdc, VDP_END, *priv, vstrlen(*priv));
832 24
        if (r != 0)
833 0
                return (r);
834
        // only to be called once
835 24
        return (1);
836 24
}
837
838
static int v_matchproto_(vdp_fini_f)
839 32
xyzzy_string_fini(struct vdp_ctx *vdc, void **priv)
840
{
841 32
        (void)vdc;
842 32
        AN(priv);
843 32
        *priv = NULL;
844 32
        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 16
xyzzy_body_string(VRT_CTX, VCL_STRING s)
856
{
857
        struct vmod_priv *p;
858
859 16
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
860 16
        p = VRT_priv_task(ctx, string_priv_id);
861 16
        if (p == NULL)
862 0
                return;
863 16
        p->priv = TRUST_ME(s);
864 16
}
865
866
/**********************************************************************/
867
868
static int v_matchproto_(vdp_init_f)
869 8
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 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
877 8
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
878 8
        AN(vdc->clen);
879
880 8
        task = VRT_priv_task_get(ctx, priv_task_id_bp);
881 8
        if (task == NULL)
882 0
                return (1);
883 8
        CAST_OBJ_NOTNULL(bp, task->priv, XYZZY_BP_MAGIC);
884 8
        AN(priv);
885 8
        AZ(*priv);
886 8
        *priv = bp;
887
888 8
        if (*vdc->clen < 0)
889 0
                return (0);
890
891 8
        l = 0;
892 24
        VSTAILQ_FOREACH(bps, &bp->head, list)
893 16
                l += vstrlen(bps->s);
894 8
        *vdc->clen += l;
895
896 8
        return (0);
897 8
}
898
899
static int v_matchproto_(vdp_bytes_f)
900 16
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 16
        AN(priv);
907 16
        CAST_OBJ_NOTNULL(bp, *priv, XYZZY_BP_MAGIC);
908
909 32
        while ((bps = VSTAILQ_FIRST(&bp->head)) != NULL) {
910 16
                VSTAILQ_REMOVE_HEAD(&bp->head, list);
911 16
                if (VDP_bytes(vdc, VDP_NULL, bps->s, vstrlen(bps->s)))
912 0
                        return (vdc->retval);
913
        }
914
915 16
        return (VDP_bytes(vdc, act, ptr, len));
916 16
}
917
918
static int v_matchproto_(vdp_fini_f)
919 8
xyzzy_vdp_body_prefix_fini(struct vdp_ctx *vdc, void **priv)
920
{
921 8
        (void)vdc;
922 8
        AN(priv);
923 8
        *priv = NULL;
924 8
        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 420
debug_add_filters(VRT_CTX)
936
{
937 420
        AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow));
938 420
        AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13));
939 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic));
940 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked));
941 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256));
942 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32));
943 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chklen));
944 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_awshog));
945 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_string));
946 420
        AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_body_prefix));
947 420
}
948
949
void
950 92
debug_remove_filters(VRT_CTX)
951
{
952 92
        VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow);
953 92
        VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13);
954 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic);
955 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked);
956 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256);
957 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32);
958 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chklen);
959 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_awshog);
960 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_string);
961 92
        VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_body_prefix);
962 92
}